beep関数で音を鳴らすと音量が大きすぎる
M5Stackで一通り機能を試してみよう!と音を出そうとして、とりあえず一番簡単なbeep関数で音を鳴らしてみると、部屋に
ピー!!
と大きめの音が鳴ってびっくりしました。
今回はその解決方法を探っていきたいと思います。
ヘッダファイルの中身を見てみる
短いのでとりあえずM5Stack.hの中でスピーカーに関係するところを全て載せます。
Speaker.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
#include “Speaker.h” SPEAKER::SPEAKER(void) { _volume = 8; _begun = false; } void SPEAKER::begin() { _begun = true; ledcSetup(TONE_PIN_CHANNEL, 0, 13); ledcAttachPin(SPEAKER_PIN, TONE_PIN_CHANNEL); setBeep(1000, 100); } void SPEAKER::end() { mute(); ledcDetachPin(SPEAKER_PIN); _begun = false; } void SPEAKER::tone(uint16_t frequency) { if(!_begun) begin(); ledcWriteTone(TONE_PIN_CHANNEL, frequency); } void SPEAKER::tone(uint16_t frequency, uint32_t duration) { tone(frequency); _count = millis() + duration; speaker_on = 1; } void SPEAKER::beep() { if(!_begun) begin(); tone(_beep_freq, _beep_duration); } void SPEAKER::setBeep(uint16_t frequency, uint16_t duration) { _beep_freq = frequency; _beep_duration = duration; } void SPEAKER::setVolume(uint8_t volume) { _volume = 11 – volume; } void SPEAKER::mute() { ledcWriteTone(TONE_PIN_CHANNEL, 0); digitalWrite(SPEAKER_PIN, 0); } void SPEAKER::update() { if(speaker_on) { if(millis() > _count) { speaker_on = 0; mute(); } } } void SPEAKER::write(uint8_t value) { dacWrite(SPEAKER_PIN, value); } void SPEAKER::playMusic(const uint8_t* music_data, uint16_t sample_rate) { uint32_t length = strlen((char*)music_data); uint16_t delay_interval = ((uint32_t)1000000/ sample_rate); if(_volume !=11) { for(int i =0; i < length; i++) { dacWrite(SPEAKER_PIN, music_data[i] / _volume); delayMicroseconds(delay_interval); } for(int t = music_data[length -1] / _volume; t >=0; t–) { dacWrite(SPEAKER_PIN, t); delay(2); } } // ledcSetup(TONE_PIN_CHANNEL, 0, 13); ledcAttachPin(SPEAKER_PIN, TONE_PIN_CHANNEL); } |
ソースコードのリンク(2019年9月現在)
このソースコードから
- スピーカーピンとトーンピンがある (8行目 void SPEAKER::begin )
- スピーカーピンには音量がアナログで書き込めるが、トーンピンには周波数がアナログで書き込める(21行目 void SPEAKER::tone, 64行目void SPEAKER::playMusic)
ということがわかります。つまり、playMusic関数では音量を調整できますがbeep関数では音量を調整できないようです。ビープ音の音量を調整するために、3つの方法を検討しました。
解決法① setVolume関数を使う
せっかくsetVolome関数で音量調整ができるので、それを活用していきましょう。
setVolumeで音量を11にして、正弦波の音データを生成してそれをplayMusicで流します。
以下サンプルコード
playBeepでmakeBeepを呼び出し、音データを生成し、playMusicで再生しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
#include <M5Stack.h> #define pi 3.1415926535 const uint16_t sampleRate =3000; int Volume=0; void setup() { // put your setup code here, to run once: M5.begin(); M5.Speaker.begin(); M5.Speaker.setVolume(Volume); playBeep(1000, 100); } void loop() { // put your main code here, to run repeatedly: } void playBeep(int freq, int duration){ int n = duration*sampleRate/1000; uint8_t MusicData[n]; makeBeep(MusicData, freq, n, sampleRate); M5.Speaker.playMusic(MusicData, sampleRate); } void makeBeep(uint8_t* MusicData, int freq, int n, int sampleRate){ //M5.Lcd.fillRect(0,30,320,210,DARKGREY); //M5.Lcd.setCursor(0,30); for(int i=0;i<n;i++){ MusicData[i] = 127+128sin(2*pi*freq*i/sampleRate); } } |
解決法② 音源を小さくする
それでもまだ音が大きいと感じたのでさらに音を小さくしていきます。
音源データの振幅自体を小さくしていけばさらに音を小さくすることができます。
以下サンプルコード
vが振幅を表しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
#include <M5Stack.h> #define pi 3.1415926535 const uint16_t sampleRate = 3000; const int amplitude = 256; int Volume=0; double v=0.1; void setup() { // put your setup code here, to run once: M5.begin(); M5.Speaker.begin(); M5.Speaker.setVolume(Volume); } void loop() { // put your main code here, to run repeatedly: } void playBeep(int freq, int duration, double v){ int n = duration*sampleRate/1000; uint8_t MusicData[n]; makeBeep(MusicData, freq, n, sampleRate, v); M5.Speaker.playMusic(MusicData, sampleRate); } void makeBeep(uint8_t* MusicData, int freq, int n, int sampleRate, double v){ //M5.Lcd.fillRect(0,30,320,210,DARKGREY); //M5.Lcd.setCursor(0,30); for(int i=0;i<n;i++){ MusicData[i] = 127+128*v*sin(2*pi*freq*i/sampleRate); } } |
解決法③ ハードウェア的解決
そもそもスピーカーにつながっているアンプの増幅率が大きすぎるのが原因らしいので、そこに抵抗を入れたりすると音量を小さくすることができるようです。(未検証)
さらに、原始的な方法としてスピーカーにテープなどを貼ると音量を小さくできます。
参考サイト M5Stackのスピーカボリューム調整機構
まとめ
そもそもスピーカーの性能があまり良くないので難しいですが、playMusic関数を用いることでなんとか音は小さくできました。
次は音を出していないときにも勝手に出ている音をなんとかしたいですね。