2009-05-20 170 views
6

如果我要用揚聲器編程一個微控制器(ATMega128)來播放真實音調,我該怎麼做?如何發送聲音給揚聲器

我是否需要使用數字/模擬轉換器來發送不同的幅度值,還是對頻率變化足夠了?無論如何,我如何編碼揚聲器需要接收的頻率和幅度值?我需要某種頻率複用嗎?我不是在談論用發言者發出簡單的聲音,如一個音符,然後是另一個音符。我想用所有的樂器,人聲等來演奏真正的歌曲。

回答

0

你可以看看open source MP3 player,看看它們是如何做到的。我的猜測是,你需要一個D/A轉換器才能產生出色的音質。

+0

有趣的項目,但不幸的是他「聲音」的聲音解碼部分到第三方芯片: 「另一個板載芯片是來自芬蘭VLSI的VS1011,它是一個.mp3和.wav解碼器芯片,一個DAC和一個耳機放大器都在一個28引腳封裝「 我自己做了之後,只是爲了學習:) – palako 2009-05-20 22:28:12

6

假設你有一個未壓縮的8位22.1  千赫單波文件:

1)除去了標題
2)每1 /第二萬二千百第二:
2.1)讀取8位
2.2 )使用的DAC轉換到揚聲器的電壓範圍
2.3),它發送到揚聲器

這會給你[22.1  千赫/ 8位/單聲道]品質的聲音,是發揮現實樣本的簡單方法。

所有頻率的東西是不同的合成器所必需的。例如,PC揚聲器實際上是一個位。爲了具有不同的幅度(比'無'和'最大'),可能需要一些技巧,如脈寬調製(如你所說的那樣改變頻率,所以說話者的隔膜有效地具有比兩個更多的位置)。

但是你不需要爲此煩惱。您只需要在揚聲器上每秒發出22,100或44,200個聲音樣本,例如每個樣本8或16位來表示振幅。

+0

非常有趣。所以從你的回答中,我認爲WAV文件實際上是聲音本身的非常真實的表現。這只是將WAV轉換爲其所代表的模擬信號的問題。我會試試這個。 – palako 2009-05-20 22:29:32

+2

DAC部分可以用一個(相對)簡單的R-2R梯子來完成。 http://en.wikipedia.org/wiki/Resistor_Ladder。 – Evansbee 2009-05-21 00:49:11

+1

這取決於WAV文件。 WAV格式實際上可以包含壓縮音頻 - 完整格式規範可在此處獲得:http://msdn.microsoft.com/en-us/library/ms713497.aspx – 2009-05-21 04:35:26

1

如果您覺得特別有創意,可以使用resistor ladder構建您自己的數模轉換器。

0

ATMega128上沒有足夠的空間來做任何太花哨的事情。連接揚聲器(小2" 或更小)的最簡單的方法是通過一個電阻。檢查輸出的電流吸收能力,並相應地計算R。

---------------------- +V 
    | 
    \ 
    /R 
    \ 
    /   ---------- 
    |    | 
    | ------  | 
    ----| |-----| Microcontroller 
     / \  | 
     -------- | 
     Speaker --------- 

至於生產音,輸出的基本交換將會產生基本的stylaphone sound crapolla,你可以使用脈衝寬度調製來產生任何模擬聲音的近似值(這裏太複雜了,AtMega可能沒有足夠的吸氣或存儲),這是用來製作音頻驅動程序的方法對於沒有聲卡的電腦(只有內置揚聲器)在良好的時間...

2

今天,從8位微控制器播放MP3文件既簡單又便宜,您需要一個內存(例如SD卡)和MP3芯片組。例如,請參閱此article。你可以在avrfreaks找到更多。您還可以在沒有外接芯片的情況下找到播放聲音的文章。

您可以用Pulse-width modulation(PWM)播放基本聲音,但對於真正的歌曲,您需要一個DAC。我見過只使用DAC和軟件播放MP3文件的項目,但他們涉及更強大的ARM微控制器。

0

如果您使用的是Arduino,您可以以22美元購買Lady Ada的WaveShield。 Lady Ada提供許多值得購買的Arduino goodies。一些例子是GPS,以太網和步進/伺服屏蔽。

4

我試過類似的東西。首先,單片機上沒有足夠的內存來存儲真正的歌曲。你需要外部內存來處理。這意味着使用SPI接口連接外部閃存或EEPROM等。 SD也很好 - 我相信這是一個SPI風格的界面。 ATMegas有代碼與SD卡連接。

第二大問題是以適當的格式獲取數據。我會這樣做的方式是使用pulse-width modulation(PWM)來創建不同的電壓水平。我相信你在這個微控制器上有一個16位的PWM,所以你的聲音可以有16位的保真度。如果你有空間問題,你可以使用8位PWM。因此,您的聲音數據必須位於8位或16位PCM中,0x0000爲最低值,0xFFFF爲最高值。如果您想要高保真音樂,則必須具有44   KHz的採樣率才能獲得所有良好的諧波等。我相信這是PCM - 與在PC上調用相同。

那麼你將擁有所有這些值 - 對於五分鐘的音樂,你將有5 * 60 * 44000 = 13,200,000 16位值,它是211,200,000位(211兆位,26.4兆字節)。這些是您對原始數據的存儲要求。 MP3是一種可能 - 有外部芯片,但你仍然有很大的空間需求。

因此,每1/44000秒就會更新PWM寄存器中的值。您的PWM頻率必須高於4或5 - 即每個值5個PWM週期。

這是您的通用算法 - 更新PWM寄存器中的值,並讓它一直持續到結束。您至少需要一個輸出濾波器 - 將頻率限制在20KHz的可聽範圍內(如果您是發燒友的話)。一個RC濾波器可以工作,但我會選擇一個有源濾波器,因爲如果你使用PWM,你的輸出範圍通常爲0到5V,平均電壓約爲2.5V。演講者不喜歡DC水平 - 只是信號。漂亮的平均電壓爲0的正弦波。所以你的有源濾波器將不得不調整電壓電平,並使用雙電源來提供負電壓。您還可以放大大抽貝司的信號。只是不要吹出你的揚聲器。

對於PCM來說,MP3可能是更好的選擇。有芯片:http://www.sparkfun.com/commerce/product_info.php?products_id=8892

然而,這是一個完整的微控制器。你已經有一個。但是,讓我們面對它 - ATMega不會很快就會自己做MP3,不管你如何爵士樂。

它看起來像上面提到的waveshield基本上這樣做 - 使用SD卡存儲PCM和外部放大器的聲音。祝你好運!

2

產生穩定音的一種方法是直接數字合成。您需要一個DAC,無論是專用芯片還是電阻器階梯。

您設置了一個計數器,以您想要生成的頻率進行溢出,並在計數器的每個計數器上使用它來索引波表並獲得DAC的輸出值。

我已經爲New Noises From MidiVox寫過幾種不同的Arduino音調生成技術。 DAC更新代碼特定於MidiVox(和Adafruit WaveShield's)MCP4921,但正弦波的產生應該是普遍適用的。我試着將代碼大部分保存到ATmegas中,但是有幾個Arduino-isms悄然進入。

從該帖子粘貼,這裏有一些代碼在一個Arduino上用MCP4921 SPI總線上:

uint16_t sample = 0; 

/* incr = freq * (2^16/15625) 
* So for 440Hz, incr = 1845 */ 
uint16_t incr = 1845; 

/* oscillator position */ 
uint16_t pos = 0; 

const uint8_t sine[] = { 
    0x80, 0x83, 0x86, 0x89, 0x8C, 0x8F, 0x92, 0x95, 0x98, 0x9B, 0x9E, 0xA2, 
    0xA5, 0xA7, 0xAA, 0xAD, 0xB0, 0xB3, 0xB6, 0xB9, 0xBC, 0xBE, 0xC1, 0xC4, 
    0xC6, 0xC9, 0xCB, 0xCE, 0xD0, 0xD3, 0xD5, 0xD7, 0xDA, 0xDC, 0xDE, 0xE0, 
    0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEB, 0xED, 0xEE, 0xF0, 0xF1, 0xF3, 0xF4, 
    0xF5, 0xF6, 0xF8, 0xF9, 0xFA, 0xFA, 0xFB, 0xFC, 0xFD, 0xFD, 0xFE, 0xFE, 
    0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0xFE, 0xFD, 
    0xFD, 0xFC, 0xFB, 0xFA, 0xFA, 0xF9, 0xF8, 0xF6, 0xF5, 0xF4, 0xF3, 0xF1, 
    0xF0, 0xEE, 0xED, 0xEB, 0xEA, 0xE8, 0xE6, 0xE4, 0xE2, 0xE0, 0xDE, 0xDC, 
    0xDA, 0xD7, 0xD5, 0xD3, 0xD0, 0xCE, 0xCB, 0xC9, 0xC6, 0xC4, 0xC1, 0xBE, 
    0xBC, 0xB9, 0xB6, 0xB3, 0xB0, 0xAD, 0xAA, 0xA7, 0xA5, 0xA2, 0x9E, 0x9B, 
    0x98, 0x95, 0x92, 0x8F, 0x8C, 0x89, 0x86, 0x83, 0x80, 0x7D, 0x7A, 0x77, 
    0x74, 0x71, 0x6E, 0x6B, 0x68, 0x65, 0x62, 0x5E, 0x5B, 0x59, 0x56, 0x53, 
    0x50, 0x4D, 0x4A, 0x47, 0x44, 0x42, 0x3F, 0x3C, 0x3A, 0x37, 0x35, 0x32, 
    0x30, 0x2D, 0x2B, 0x29, 0x26, 0x24, 0x22, 0x20, 0x1E, 0x1C, 0x1A, 0x18, 
    0x16, 0x15, 0x13, 0x12, 0x10, 0x0F, 0x0D, 0x0C, 0x0B, 0x0A, 0x08, 0x07, 
    0x06, 0x06, 0x05, 0x04, 0x03, 0x03, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 
    0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x03, 0x03, 0x04, 0x05, 0x06, 
    0x06, 0x07, 0x08, 0x0A, 0x0B, 0x0C, 0x0D, 0x0F, 0x10, 0x12, 0x13, 0x15, 
    0x16, 0x18, 0x1A, 0x1C, 0x1E, 0x20, 0x22, 0x24, 0x26, 0x29, 0x2B, 0x2D, 
    0x30, 0x32, 0x35, 0x37, 0x3A, 0x3C, 0x3F, 0x42, 0x44, 0x47, 0x4A, 0x4D, 
    0x50, 0x53, 0x56, 0x59, 0x5B, 0x5E, 0x62, 0x65, 0x68, 0x6B, 0x6E, 0x71, 
    0x74, 0x77, 0x7A, 0x7D 
}; 

void setup() { 
    cli(); 

    /* Enable interrupt on timer2 == 127, with clk/8 prescaler. At 16MHz, 
     this gives a timer interrupt at 15625Hz. */ 
    TIMSK2 = (1 << OCIE2A); 
    OCR2A = 127; 

    /* clear/reset timer on match */ 
    TCCR2A = 1<<WGM21 | 0<<WGM20; /* CTC mode, reset on match */ 
    TCCR2B = 0<<CS22 | 1<<CS21 | 0<<CS20; /* clk, /8 prescaler */ 

    SPCR = 0x50; 
    SPSR = 0x01; 
    DDRB |= 0x2E; 
    PORTB |= (1<<1); 

    sei(); 
} 

ISR(TIMER2_COMPA_vect) { 
    /* OCR2A has been cleared, per TCCR2A above */ 
    OCR2A = 127; 

    pos += incr; 

    /* shift left a couple of bits for more volume */ 
    sample = sine[highByte(pos)] << 2; 

    PORTB &= ~(1<<1); 

    /* buffered, 1x gain, active mode */ 
    SPDR = highByte(sample) | 0x70; 
    while (!(SPSR & (1<<SPIF))); 

    SPDR = lowByte(sample); 
    while (!(SPSR & (1<<SPIF))); 

    PORTB |= (1<<1); 
} 

void loop() { 
} 

有關直接數字合成的漂亮的事情是,它是非常容易發揮多個音調在一起(添加),或在所需卷(添加前通過的體積乘以)其混合。

我發現Arduino可以使用這種方法同時播放約30個音調。我的具體應用是Hammond organ simulation,這也可能證明有用的閱讀。

相關問題