Propellerで音を出そうとする
構造体の話とか全然触れられていないのだけれど、パララックスの公式gccチュートリアルは終わってしまったので、さて、どうしようか、というところでまずは音を出してみようと思い立った。
回路のチュートリアルで音を出したのはあったけれど、あれはデジタルアウトのオンオフで矩形波を出していただけなので、ちゃんとしたD/Aで音を出してみたい。
プロペラチップの公式言語であるSPINだと音を出すライブラリやらサンプルはあるんだけれど、C言語版はよく判っていない。長嶋先生のHPを前に読んだ時にΣΔ変調で音を出す、それは1bitサンプリングでやっている、というところまでは読んだ記憶があるが、それっきりであります。
右も左も判らないので、とにかく既にあるソースを読みたいがどうしよう、と思っていたら、spin言語のソースファイルをC言語のソースに変換してくれる公式ツールがspin2cppってのがあるのを思い出して、さっそくやってみた。
ところが名前ですぐ気がつけば良かったんだけれども、CじゃなくてC++に変換するうえ、インラインアセンブラがメインなので、さっぱり参考にならない。
困ったな、というところでC言語でWAVファイルの再生をする例があるのを思い出して、それを見ることにした。作例としてはSDカードをマウントしてその中にあるファイルを読みだして再生する、というもの。
SDカードのマウントとかWAVファイルの読み込みとかの関数を分解していけば、値と出力ピンを指定すれば音が出るようなライブラリがあるんじゃないかと思ったけれど、そうは甘くなくて、長嶋先生のHPでspinでやっていることをC言語でもやらなくてはならないことが判った。
キモになっているのがここ。
void audio_dac(void *par)
{
while(!playing);
CTRA = 0x18000000 + 27;
CTRB = 0x18000000 + 26;
DIRA |= (1<<27);
DIRA |= (1<<26);
dtSample = CLKFREQ/sampleRate;
int i;
int t = CNT;
t += dtSample;
while(1)
{
if(playing)
{
swap = 1;
for(i = 0; i < BUF_SIZE; i+=2)
{
wavVal = wavDacBufferL[i] | wavDacBufferL[i+1]<<8;
dacVal = (wavVal + 32768) * volume;
FRQA = dacVal;
FRQB = dacVal;
waitcnt(t+=dtSample);
}
swap = 2;
for(i = 0; i < BUF_SIZE; i+=2)
{
wavVal = wavDacBufferH[i] | wavDacBufferH[i+1]<<8;
dacVal = (wavVal + 32768) * volume;
FRQA = dacVal;
FRQB = dacVal;
waitcnt(t+=dtSample);
}
}
else
{
dacVal = 32768 * volume;
FRQA = dacVal;
FRQB = dacVal;
waitcnt(t+=dtSample);
}
}
}
wavValはSDを読み込んだ時のバッファなので、一番の核心はCTRA、CTRBに値を設定してFRQAとFRQBに音のデータを渡せば音が出る、というところまではおぼろげながら判るんだけれど、その4単語がよく判らない。長嶋先生のHPの該当箇所と日本語資料を読めばレジスタということが判ってカウンタが関わっているのは判るのだけれど、何しろCPUの働きとかについて良く理解していないので、イメージがつかめない。
C言語の話も手探り状態なのに、いきなりアセンブラレベルなので厳しいのは判っていたが、プロペラ自体が変わったマイコンなので多分、初学者には難しいんだろうなあ、と。
とにかく、今日はC言語で音を出すにあたって核心部分がが明らかになっただけでも進歩ってもんでありましょう。