以前、
MIDIから出力したノート+時間のデータを使って、micro:bitで音を鳴らす
という実験をやったのですが、少し長めのデータを使うとmicro:bitがメモリ不足におちいってしまうため、これまではシリアル経由でPCからデータを送っていました。
ですが、やはりmicro:bit単体で鳴らしたくなり、PlatformIOを使ってみることにしました。
PlatformIOはVisualStudioCodeのプラグインの形で提供されているIDEです。
適当なプロジェクト名を付け、Board:
のところにmicro:bit
と入力すると出てきます。
Finishボタンを押すとプロジェクトが作成されます。
FrameWorkはArduinoで開発したかったのですが、BoardがArduino以外だと音を出すTone()関数が使えないようでしたので、mbedで開発することにしました。
左ペインでplatformio.ini
を選択し、framework = mbed
に書き換えて保存します。
次に左ペインのsrc>main.cppを選択し、プログラムを書き換えます
#include <mbed.h>
// LED(2,2)
DigitalOut row(P0_14);
DigitalOut col(P0_6, 0);
const int mididata[]={0, 768, 86, 235, 0, 5, 86, 475, 0, 5, 88, 235, 0, 5, 88, 235, 0, 5, 88, 235, 0, 5, 89, 475, 0, 5, 94, 715, 0, 245, 89, 235, 0, 5, 89, 235, 0, 5, 91, 475, 0, 5, 91, 715, 0, 5, 89, 1195, 0, 2165, 84, 235, 0, 5, 84, 235, 0, 5, 84, 235, 0, 5, 84, 235, 0, 5, 84, 235, 0, 5, 86, 235, 0, 5, 84, 475, 0, 5, 84, 235, 0, 5, 84, 235, 0, 5, 84, 235, 0, 5, 84, 235, 0, 5, 84, 235, 0, 5, 86, 475, 0, 5, 84, 715, 0, 5, 82, 115, 0, 5, 81, 115, 0, 5, 82, 2395, 0, 725, 79, 475, 0, 5, 79, 475, 0, 5, 79, 235, 0, 5, 79, 235, 0, 5, 79, 235, 0, 5, 79, 235, 0, 725, 82, 235, 0, 245, 82, 235, 0, 5, 84, 235, 0, 4085, 84, 235, 0, 5, 84, 235, 0, 5, 84, 235, 0, 5, 84, 235, 0, 5, 84, 235, 0, 5, 84, 235, 0, 5, 84, 235, 0, 965, 84, 475, 0, 5, 86, 475, 0, 5, 91, 715, 0, 5, 86, 1195, 0, 2165, 88, 235, 0, 5, 88, 235, 0, 5, 88, 235, 0, 5, 88, 235, 0, 5, 88, 235, 0, 5, 88, 235, 0, 5, 88, 235, 0, 965, 89, 475, 0, 5, 91, 475, 0, 5, 91, 475, 0, 245, 89, 1195, 0, 1925, 86, 475, 0, 5, 86, 235, 0, 245, 86, 235, 0, 485, 81, 235, 0, 965, 86, 475, 0, 5, 89, 475, 0, 5, 91, 715, 0, 5, 89, 115, 0, 5, 88, 115, 0, 5, 89, 2395, 0, 485, 84, 955, 0, 5, 86, 955, 0, 5, 88, 955, 0, 5, 84, 955, 0, 5, 81, 1915, 0, 1925, 86, 475, 0, 5, 86, 235, 0, 5, 86, 235, 0, 5, 86, 235, 0, 5, 86, 475, 0, 5, 81, 475, 0, 725, 86, 475, 0, 5, 89, 475, 0, 5, 91, 715, 0, 5, 86, 2155, 0, 965, 88, 955, 0, 5, 88, 955, 0, 5, 88, 475, 0, 485, 84, 235, 0, 5, 84, 235, 0, 5, 86, 235, 0, 245, 88, 115, 0, 5, 91, 115, 0, 5, 96, 115, 0, 5, 100, 115, 0, 5, 103, 115, 0, 5, 100, 115, 0, 5, 96, 115, 0, 5, 91, 115, 0, 5, 88, 115, 0, 5, 91, 115, 0, 5, 96, 115, 0, 5, 100, 115, 0, 5, 103, 115, 0, 5, 100, 115, 0, 5, 96, 115, 0, 5, 91, 115, 0, 245, 0, 20, 0, 20, 96, 75, 100, 20, 103, 20, 0, 85, 0, 20, 0, 20, 96, 75, 100, 20, 103, 20, 0, 85, 0, 20, 0, 20, 96, 75, 100, 20, 103, 20, 0, 85, 0, 20, 0, 20, 96, 75, 100, 20, 103, 20, 0, 85, 0, 20, 0, 20, 96, 75, 100, 20, 103, 20, 0, 85, 0, 20, 0, 20, 96, 75, 100, 20, 103, 20, 0, 85, 0, 20, 0, 20, 96, 75, 100, 20, 103, 20, 0, 85, 93, 235, 0, 5, 93, 475, 0, 5, 89, 475, 0, 5, 89, 235, 0, 5, 89, 475, 0, 5, 91, 235, 0, 5, 91, 235, 0, 5, 89, 475, 0, 5, 88, 235, 0, 5, 88, 235, 0, 5, 89, 235, 0, 5, 89, 235, 0, 5, 91, 235, 0, 5, 91, 235, 0, 5, 91, 475, 0, 5, 93, 475, 0, 5, 91, 1435, 0, 965, 93, 235, 0, 5, 93, 475, 0, 5, 89, 475, 0, 5, 89, 235, 0, 5, 89, 475, 0, 5, 91, 475, 0, 5, 89, 475, 0, 5, 88, 235, 0, 245, 89, 475, 0, 5, 91, 235, 0, 5, 91, 235, 0, 5, 91, 475, 0, 5, 91, 955, 0, 1925, 93, 235, 0, 5, 93, 475, 0, 5, 89, 475, 0, 5, 89, 235, 0, 5, 89, 475, 0, 5, 91, 235, 0, 5, 91, 235, 0, 5, 89, 475, 0, 5, 88, 475, 0, 5, 89, 235, 0, 5, 89, 235, 0, 5, 91, 235, 0, 5, 91, 235, 0, 5, 91, 475, 0, 5, 93, 475, 0, 5, 91, 1435, 0, 965, 86, 235, 0, 5, 86, 475, 0, 5, 88, 475, 0, 5, 88, 235, 0, 5, 89, 475, 0, 5, 94, 235, 0, 5, 94, 235, 0, 5, 93, 235, 0, 5, 93, 235, 0, 5, 89, 235, 0, 5, 89, 235, 0, 5, 91, 475, 0, 5, 91, 715, 0, 5, 89, 235, 0, 5, 89, 955, 0, 1925, 86, 475, 0, 5, 86, 475, 0, 5, 88, 475, 0, 5, 89, 475, 0, 5, 94, 715, 0, 245, 89, 475, 0, 5, 91, 475, 0, 5, 91, 715, 0, 5, 89, 1195, 0, 10 };
const float tempoRate=0.00075;
int midiPeriod[128];
int main() {
PwmOut* pPo = new PwmOut(P0);
for(int i=0;i<128;++i){
double freq = 440.0 * pow(2.0 , (double)(i - 69) / 12.0);
midiPeriod[i] = (freq>10) ? (int)(1000000.0/freq) : 0;
}
int szh=sizeof(mididata)>>1;
for(int i=0;i<szh;++i){
int period = midiPeriod[mididata[(i<<1)+0]];
pPo->period_us(period);
pPo->pulsewidth_us(period>>1);
row = (period>0) ? 1 : 0; // led
wait((float)(mididata[(i<<1)+1])*tempoRate);
}
pPo->period_us(1);
pPo->pulsewidth_us(0);
}
保存したらmicro:bitをUSBでPCと接続し、下段にある→を押してビルド&転送します。
micro:bitのエディタから転送したときはメモリ不足でハングアップしていましたが、今回は余裕でした。
また、micro:bitのエディタでは精度が出なかったためテーブル化していた midiノートから周波数を求める式 も、
PlatformIO では計算で正しい値を求めることができました(ここでは周波数ではなく時間[μs])。
for(int i=0;i<128;++i){
double freq = 440.0 * pow(2.0 , (double)(i - 69) / 12.0);
midiPeriod[i] = (freq>10) ? (int)(1000000.0/freq) : 0;
}