[[戻る>TinyArcade]]

*サウンド再生 [#ac881d44]
サウンドを再生するだけのプログラムです。どうしても長くなってしまう・・・。~
本当はすべてinoファイルに書こうと思たんだけどどうしても~
 void TC5_Handler(void) __attribute__ ((weak, alias("SoundStreamCallback")));~
の行でエラーになってしまったのでcppファイルに分割しました。TC5_Handlerはinoファイル内では書けないのかな?~
とにかくわかる範囲で説明。~
TCは多分タイムカウンタの事。このカウンタ使って周期的に割り込み処理を起こしてその中で10bitDACにデータを書き込み音を再生している。~
このプログラムでは1秒間に11025回の割り込み処理を起こしその度にstream_buffer内の1バイトを10bitDACに送っている。~
10bitDACに送るデータ形式は符号なし10bitデータなので符号なし8bitデータを用意して割り込み処理内でデータを<<2して送っている。~
stream_bufferはリングバッファになっていて800バイト確保して前半400バイトを再生している場合は後半400バイトをデータ更新、後半400バイトを再生している場合は前半400バイトをデータ更新している。~
UpdateSoundStream()はloopで毎回呼び出す必要があり、GetSoundStreamWritableSize()でサウンドバッファに書き込みするバイト数を取得して0以外ならWriteSoundStream()でwaveデータを書き込む。~
このプログラムはwaveの終端になったらwaveの先頭に戻ってループ再生している。~
またTinyArcadeは1チャンネル分しかサウンドを再生することができないためBGM,SEなどたくさん同時に再生したい場合は自前でwaveを合成する必要がある。~
~
要するにこのプログラムはBGM再生中にSEが再生できないためすぐにはゲームに使えない…。~
要するにこのプログラムはBGM再生中にSEが再生できないためこのままゲームプログラムに使えない…。~
*サンプルプログラム [#qe1538e7]
-SoundSample1.ino
 #include <TinyScreen.h>
 #include "SoundStream.hpp"
 #include "TwinkleBeep01.h"
 
 TinyScreen tiny_screen = TinyScreen(TinyScreenPlus);
 int wave_sample;
 
 void setup()
 {
 	tiny_screen.begin();
 	tiny_screen.setBitDepth(TSBitDepth8);
 	tiny_screen.setBrightness(8);
 	tiny_screen.setFont(liberationSansNarrow_12ptFontInfo);
 	tiny_screen.fontColor(TS_8b_White, TS_8b_Black);
 	InitializeSoundStream();
 	wave_sample = 0;
 }
 
 void loop()
 {
 	tiny_screen.setCursor(0,0);
 	tiny_screen.print("Now playing!");
 	UpdateSoundStream();
 	int writable_size = GetSoundStreamWritableSize();
 	int wave_size = static_cast<int>(sizeof(TwinkleBeep01_wave));
 	if(writable_size > 0)
 	{
 		size_t write_size = writable_size;
 		size_t left_size = wave_size - wave_sample;
 		if(left_size < writable_size)
 		{
 			write_size = left_size;
 		}
 		if(write_size > 0)
 		{
 			unsigned char* write_wave_buffer = new unsigned char[writable_size];
 			memcpy(write_wave_buffer, &TwinkleBeep01_wave[wave_sample], write_size);
 			wave_sample += write_size;
 			if(writable_size > left_size)
 			{
 				int left_write_size = writable_size - left_size;
 				if(left_write_size > 0)
 				{
 					wave_sample = 0;
 					memcpy(&write_wave_buffer[write_size], &TwinkleBeep01_wave[wave_sample], left_write_size);
 					wave_sample += left_write_size;
 				}
 			}
 			WriteSoundStream(write_wave_buffer);
 			delete [] write_wave_buffer;
 		}
 		if(wave_sample >= wave_size)
 		{
 			wave_sample = 0;
 		}
 	}
}
-SoundStream.hpp
 #ifndef SOUNDSTREAM_HPP
 #define SOUNDSTREAM_HPP
 
 static const int SOUND_BUFFER_SIZE = 800;
 static const int SOUND_BUFFER_SIZE_HALF = SOUND_BUFFER_SIZE / 2;
 static const int SOUND_FREQUENCY = 11025;
 
 void InitializeSoundStream();
 void FinalizeSoundStream(void);
 void UpdateSoundStream(void);
 int GetSoundStreamWritableSize(void);
 bool WriteSoundStream(const unsigned char* buffer);
 
 #endif
-SoundStream.cpp
 #include <TinyScreen.h>
 #include "SoundStream.hpp"
 
 unsigned char stream_buffer[SOUND_BUFFER_SIZE];
 int sample_index;
 int write_buffer;
 bool request;
 
 bool tcIsSyncing(void)
 {
 	return TC5->COUNT16.STATUS.reg & TC_STATUS_SYNCBUSY;
 }
 
 void tcReset(void)
 {
 	// Reset TCx
 	TC5->COUNT16.CTRLA.reg = TC_CTRLA_SWRST;
 	while(tcIsSyncing());
 	while(TC5->COUNT16.CTRLA.bit.SWRST);
 }
 
 void InitializeSoundStream(void)
 {
 	memset(stream_buffer, 0x80, SOUND_BUFFER_SIZE);
 	sample_index = 0;
 	write_buffer = 0;
 	request = false;
 	analogWrite(A0, 0);
 	// Enable GCLK for TCC2 and TC5 (timer counter input clock)
 	GCLK->CLKCTRL.reg = static_cast<unsigned short>((GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(GCM_TC4_TC5)));
 	while(GCLK->STATUS.bit.SYNCBUSY);
 	tcReset();
 	// Set Timer counter Mode to 16 bits
 	TC5->COUNT16.CTRLA.reg |= TC_CTRLA_MODE_COUNT16;
 	// Set TC5 mode as match frequency
 	TC5->COUNT16.CTRLA.reg |= TC_CTRLA_WAVEGEN_MFRQ;
 	TC5->COUNT16.CTRLA.reg |= TC_CTRLA_PRESCALER_DIV1;
 	TC5->COUNT16.CC[0].reg = static_cast<unsigned short>((SystemCoreClock / SOUND_FREQUENCY - 1));
 	while(tcIsSyncing());
 	// Configure interrupt request
 	NVIC_DisableIRQ(TC5_IRQn);
 	NVIC_ClearPendingIRQ(TC5_IRQn);
 	NVIC_SetPriority(TC5_IRQn, 0);
 	NVIC_EnableIRQ(TC5_IRQn);
 	// Enable the TC5 interrupt request
 	TC5->COUNT16.INTENSET.bit.MC0 = 1;
 	while(tcIsSyncing());
 	// Enable TC
 	TC5->COUNT16.CTRLA.reg |= TC_CTRLA_ENABLE;
 	while(tcIsSyncing());
 }
 
 void FinalizeSoundStream(void)
 {
 	// Disable TC5
 	TC5->COUNT16.CTRLA.reg &= ~TC_CTRLA_ENABLE;
 	while(tcIsSyncing());
 	// Reset TCx
 	TC5->COUNT16.CTRLA.reg = TC_CTRLA_SWRST;
 	while(tcIsSyncing());
 	while(TC5->COUNT16.CTRLA.bit.SWRST);
 }
 
 void UpdateSoundStream(void)
 {
 	int play_buffer = 0;
 	if(sample_index >= SOUND_BUFFER_SIZE_HALF)
 	{
 		play_buffer = 1;
 	}
 	if(write_buffer == play_buffer)
 	{
 		request = true;
 	}
 }
 
 int GetSoundStreamWritableSize(void)
 {
 	if(request == false)
 	{
 		return 0;
 	}
 	return SOUND_BUFFER_SIZE_HALF;
 }
 
 bool WriteSoundStream(const unsigned char* buffer)
 {
 	int play_buffer = 0;
 	if(sample_index >= SOUND_BUFFER_SIZE_HALF)
 	{
 		play_buffer = 1;
 	}
 	write_buffer = 1 - play_buffer;
 	memcpy(&stream_buffer[SOUND_BUFFER_SIZE_HALF * write_buffer], buffer, SOUND_BUFFER_SIZE_HALF);
 	request = false;
 	return true;
 }
 
 #ifdef __cplusplus
 extern "C"
 {
 #endif
 	void SoundStreamCallback(void)
 	{
 		while(DAC->STATUS.bit.SYNCBUSY == 1);
 		DAC->DATA.reg = static_cast<unsigned short>(stream_buffer[sample_index] << 2); // 8bit->10bit
 		while(DAC->STATUS.bit.SYNCBUSY == 1);
 		++ sample_index;
 		if(sample_index >= SOUND_BUFFER_SIZE)
 		{
 			sample_index = 0;
 		}
 		TC5->COUNT16.INTFLAG.bit.MC0 = 1;
 	}
 	void TC5_Handler(void) __attribute__ ((weak, alias("SoundStreamCallback")));
 #ifdef __cplusplus
 }
 #endif
-TwinkleBeep01.h
 // 11025Hz 8bit mono wavedata
 const unsigned char TwinkleBeep01_wave[40045] =
 {
 	128, 128, 122, 116, 113, 119, 139, 150, 152, 141, 105, 83, 79, 91, 138, 176,
 	178, 174, 128, 79, 76, 84, 132, 186, 196, 190, 151, 92, 76, 81, 112, 172,
 	197, 194, 159, 95, 64, 63, 80, 135, 178, 179, 168, 117, 67, 60, 68, 111,
 :
 :
 :
 続く
*実行結果 [#n36c708f]
#ref(SoundSample1.jpg,,,100%)
TwinkleBeep01_waveがループ再生されます。~
*サンプルプログラムのダウンロード [#s4bd33eb]
#ref(SoundSample1.zip)~

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS