コンピュータを楽しもう!!

今、自分が面白くていろいろやってみたことを書き綴りたいと思います。連絡先はtarosa.yでgmail.comです。

サウンドの拡張(2)

昨日のブログで、サウンドの拡張について書きましたが、追加した部分と方針変更した部分があるので書いておきます。

FifoMessageTypeの拡張

昨日のブログでは、FifoMessageにplaychanelを追加して、上位ビットにチャネル番号、下位ビットに制御コードを割り当てたと書きましたが、制御系はFifoMessageTypeにまとめた方がわかりやすいと考え直しました。そこで、下記のような制御パラメータを追加しました。

typedef enum {
 SOUND_PLAY_MESSAGE = 0x1234,
 SOUND_PSG_MESSAGE = 0x1235,
 SOUND_NOISE_MESSAGE = 0x1236,
 MIC_RECORD_MESSAGE = 0x1237,
 MIC_BUFFER_FULL_MESSAGE = 0x1238,
 SYS_INPUT_MESSAGE = 0x1239,
 SOUND_SET_MESSAGE_FREE = 0x123a,	//Original Extension
 SOUND_SET_MESSAGE_APPO = 0x123b,	//Original Extension
 SOUND_PLAY_MESSAGE_FREE = 0x123c,	//Original Extension
 SOUND_PLAY_MESSAGE_APPO = 0x123d	//Original Extension
}FifoMessageType;

後半4つが追加した制御コードです。

  • SOUND_SET_MESSAGE_FREE フリーのチャネルにサウンドデータをセットする
  • SOUND_SET_MESSAGE_APPO  指定チャネルにサウンドデータをセットする
  • SOUND_PLAY_MESSAGE_FREE フリーのチャネルにサウンドデータをセットして再生開始する(従来のSOUND_PLAY_MESSAGEと同じこと)
  • SOUND_PLAY_MESSAGE_APPO 指定のチャネルにサウンドデータをセットして再生を開始する。

結果的にARM9のプログラムは下記のように変更しました。

int soundPlayWave(int chanel, const void* data, SoundFormat format, u32 dataSize, u16 freq, u8 volume, u8 pan, bool loop, u32 loopPoint){ 
	
 FifoMessage msg;

 msg.type = SOUND_PLAY_MESSAGE_APPO;
 msg.SoundPlay.playchanel = (chanel<<4);
 msg.SoundPlay.data = data;
 msg.SoundPlay.freq = freq;
 msg.SoundPlay.volume = volume;
 msg.SoundPlay.pan = pan;
 msg.SoundPlay.loop = loop;
 msg.SoundPlay.format = format;
 msg.SoundPlay.loopPoint = loopPoint;
 msg.SoundPlay.dataSize = dataSize >> 2;

 fifoSendDatamsg(FIFO_USER_05, sizeof(msg), (u8*)&msg);

 while(!fifoCheckValue32(FIFO_USER_05));

 return (int)fifoGetValue32(FIFO_USER_05);
}

int soundSetWave(int chanel, const void* data, SoundFormat format, u32 dataSize, u16 freq, u8 volume, u8 pan, bool loop, u32 loopPoint){ 
	
 FifoMessage msg;

 msg.type = SOUND_SET_MESSAGE_APPO;
 msg.SoundPlay.playchanel = (chanel<<4);
 msg.SoundPlay.data = data;
 msg.SoundPlay.freq = freq;
 msg.SoundPlay.volume = volume;
 msg.SoundPlay.pan = pan;
 msg.SoundPlay.loop = loop;
 msg.SoundPlay.format = format;
 msg.SoundPlay.loopPoint = loopPoint;
 msg.SoundPlay.dataSize = dataSize >> 2;
 fifoSendDatamsg(FIFO_USER_05, sizeof(msg), (u8*)&msg);

 while(!fifoCheckValue32(FIFO_USER_05));

 return (int)fifoGetValue32(FIFO_USER_05);
}

msg.type以外全く一緒ですね。フリーチャネルにセットするだけというのは、今のところ使うことは無いので、プログラムは作っていないです。フリーチャネルにセットして再生させるのは、従来の関数でいけます。
ARM7側のプログラムは下記です。

void soundDataHandler2(int bytes, void *user_data) {
//---------------------------------------------------------------------------------
 int channel = -1;

 FifoMessage msg;

 fifoGetDatamsg(FIFO_USER_05, bytes, (u8*)&msg);

 if(msg.type == SOUND_PLAY_MESSAGE_APPO 
   || msg.type == SOUND_SET_MESSAGE_APPO
   || msg.type == SOUND_PLAY_MESSAGE_FREE
   || msg.type == SOUND_SET_MESSAGE_FREE) {

   if( msg.type == SOUND_PLAY_MESSAGE_FREE || msg.type == SOUND_SET_MESSAGE_FREE ){
     channel = getFreeChannel2(); 
   }
   else{
     channel = ((int)msg.SoundPlay.playchanel)>>4;
   }

   if(channel >= 0) {
     SCHANNEL_SOURCE(channel) = (u32)msg.SoundPlay.data;
     SCHANNEL_REPEAT_POINT(channel) = (u32)msg.SoundPlay.loopPoint;
     SCHANNEL_LENGTH(channel) = msg.SoundPlay.dataSize;
     SCHANNEL_TIMER(channel) = SOUND_FREQ( msg.SoundPlay.freq );
     if( msg.type == SOUND_PLAY_MESSAGE_FREE || msg.type == SOUND_PLAY_MESSAGE_APPO ){
       SCHANNEL_CR(channel) = SCHANNEL_ENABLE | SOUND_VOL(msg.SoundPlay.volume) | SOUND_PAN(msg.SoundPlay.pan) | (msg.SoundPlay.format << 29) | (msg.SoundPlay.loop ? SOUND_REPEAT : SOUND_ONE_SHOT);
     }
     else{
       SCHANNEL_CR(channel) = ~SCHANNEL_ENABLE &( SCHANNEL_ENABLE | SOUND_VOL(msg.SoundPlay.volume) | SOUND_PAN(msg.SoundPlay.pan) | (msg.SoundPlay.format << 29) | (msg.SoundPlay.loop ? SOUND_REPEAT : SOUND_ONE_SHOT));
     }
   }
	
   } else if(msg.type == SOUND_PLAY_MESSAGE) {

 以下省略。

SOUND_PLAY_MESSAGE_FREEを、SOUND_PLAY_MESSAGE側にもっていった方が良かったかな。こんな感じです。

何故、指定チャネルにセットしたいのか

たぶん、指定チャネルにサウンドデータをセットするというのは、あまりやらないと思います。空いているチャネルに随時セットして鳴らしていった方が、サウンドを鳴らすにはいいことが多いんですよね。
例えば、ゲームで連射の音のような同じサウンドを続けて鳴らす場合とか、同じデータを次々にオーバーラップして鳴らそうとすると、空いているチャネルにどんどん突っ込んで行かないと実現できないですよね。また、ストリーミング的にサウンドデータを転送して鳴らすことを考えたときにも、先ほどのオーバーラップができた方が、次のデータの鳴らし始めのプチノイズ発生を抑えやすいと思うのです。
で、何故、指定のチャネルにサウンドデータをセットしたかったかというと、ストリーミング再生プログラムができていないため、大容量のサウンドデータをndsのヒープ領域に確保しているので、サウンドチャネルと割りついているヒープ領域の関係を把握しておきたかっただけです。だから、普通、使っている分には余り恩恵の無い拡張だと思います。
もし、ソース公開を希望する方がいましたら「公開希望」と一声掛けてください。「うちで働いてみない?」という一言の方がよりありがたいですが・・・(^^;地方なのでね。

本当にやりたいことリスト

(ブログの終わりにやりたいことを書いておきたいと思います)

  • 求職活動・・・このブログで興味を持った人一声かけてください。m(_ _)m
  • Androidプログラム
  • Web系のプログラム