#author("2023-05-30T11:05:09+09:00","","")
#author("2023-05-30T11:06:27+09:00","","")
* DirectSound2 [#bf4bc923]
音楽データのsinged 8bit 16384hzは、素のデータであって保存形式として向いていません。もし30分の音楽データを用意した場合は30分*60秒=1800秒、1800*16384バイト=29,491,200バイトとなってしまいます。そこで圧縮しつつもCPU使用率を取らないライブラリを以下に紹介します。上2つは使ったことはありますが他は詳しくありません。ご了承ください。

** 8ad codec [#r02fc646]
https://pineight.com/gba/#8ad~
ADPCM techniques and 6 percent of the GBA's CPU time.がウリです。非常に扱いやすくソースコードも短かった為、サンプルプログラムNO.108 diabo_gbaやNO.106 kanon_gbaに採用しました。オススメの1つです。

** MaxMod [#ia541121]
https://maxmod.devkitpro.org/~
https://github.com/devkitPro/maxmod~
devkitProに標準装備されていてexamplesフォルダにサンプルコードもあります。MOD, S3M, XM, and ITとwavも対応しています。

** Apex Audio System [#efdfcaa0]
https://github.com/stuij/apex-audio-system~
MOD playing routines and support for up to 16 channels.

** Krawall [#x576fed7]
https://github.com/sebknzl/krawall~
XM/S3M Modplayer.

* ところでMod多くない? [#xd081c74]
個人的にはmidiの方が親しみを持つのですけれど、midiフォーマットですとGBサウンドの仕様を満たすのは難しいようです。modトラッカー使った方がツールも豊富です。以下に、MaxModのサンプルプログラムを用意しました。libmm.aを組み込むだけですとdevkitproのサンプルと被るので、MaxModソースコードを直接コンパイルして、libgccもお世話にならない作りにしました。

** MaxModのコンパイルメモ [#z0fc8c51]
- 1.ASFLAGS~
MakefileのASFLAGSにSYS_GBAフラグを組み込みます。MaxModの*.sファイルにDS用かGBA用かの判定がある為です。
 ASFLAGS = -DSYS_GBA

- 2._call_via_r7, _call_via_r1~
gcc_patch.sを作成してこちらで経由させます。
 // 2023/05/18 reject libgcc.
 // patched -> _call_via_r7, _call_via_r1, malloc
 
 
 	.align 0
 	.global _call_via_r7
 	.thumb_func
 
 _call_via_r7:
 	bx r7
 
 
 	.align 0
 	.global _call_via_r1
 	.thumb_func
 
 _call_via_r1:
 	bx r1

- 3. ソースコードの変更~
mm_init_default.sの71行目には、使用するチャンネル数(最大8)をmallocさせています。こちらもpatch当てて対応します。
 	mov	r6, r1				// r6=#channels
 	ldr	r0,=MM_SIZEOF_MODCH+MM_SIZEOF_ACTCH+MM_SIZEOF_MIXCH
 	mul	r0, r6
 	ldr	r4,=mixlen
 	add	r0, r4
 //	bl	malloc		patched 2023/05/18
 	bl	MallocPatch

- 4. mallocのパッチ~
自前に容量を確保します。ちなみに8chで1792バイトでした。
 #include "malloc.h"
 
 //---------------------------------------------------------------------------
 u8 MallocMem[2000];
 
 //---------------------------------------------------------------------------
 EWRAM_CODE u32* MallocPatch(u32 size)
 {
 	TRACE("MallocPatch: size=%d\n", size);
 
 	return (u32*)MallocMem;
 }

** サンプルプログラム [#m72fe206]
 #include "libmm/maxmod.h"
 #include "lib/gba.h"
 #include "irq.arm.h"
 #include "bg.h"
 #include "key.h"
 #include "res.h"
 
 //---------------------------------------------------------------------------
 // maxmodライブラリ内の非公開関数
 u32 mmMixerChannelActive(mm_word channel);
 
 //---------------------------------------------------------------------------
 // 効果音の登録(id, rate, handle, volume, panning)
 mm_sound_effect ambulance = { {SFX_AMBULANCE}, 1024, 0, 255, 0 };
 mm_sound_effect boom = { {SFX_BOOM}, 1024, 0, 255, 255 };
 
 // sound effect handle (for cancelling it later)
 mm_sfxhand amb = 0;
 
 //---------------------------------------------------------------------------
 IWRAM_CODE int main(void)
 {
 	REG_WSCNT = 0x4317;
 
 	BgInit();
 	KeyInit();
 	IrqInit();
 
 	mmInitDefault((mm_addr)soundbank_bin, 8);
 	mmStart(MOD_FLATOUTLIES, MM_PLAY_LOOP);
 
 	BgDrawPrintf(0, 0, "MaxMod Audio demo");
 	BgDrawPrintf(1, 2, "Hold  A for ambulance sound");
 	BgDrawPrintf(1, 3, "Press B for boom sound");
 	BgDrawPrintf(1, 4, "Press L for music stop");
 	BgDrawPrintf(1, 5, "Press R for music start");
 
 	BgDrawPrintf(1, 8, "CPU Usage");
 	BgDrawPrintf(1, 9, " +2.6 percent BASE");
 	BgDrawPrintf(1, 10, " +2   percent 1ch (max 8ch)");
 
 
 	for(;;)
 	{
 		VBlankIntrWait();
 
 		// start vcount 0
 		while(*(vu16*)0x4000006 != 0) {};
 
 		// パレット0を変更してcpu使用率の可視化をします
 		// mmVBlank関数は本来、vblank割り込み中に処理を行います
 
 		*(vu16*)0x5000000 = RGB5(31, 0, 0);
 		mmVBlank();
 		*(vu16*)0x5000000 = RGB5(0, 0, 31);
 		mmFrame();
 		*(vu16*)0x5000000 = RGB5( 0, 0, 0);
 
 
 		vu32 i, ch = 0;
 		for(i=0; i<8; i++)
 		{
 			if(mmMixerChannelActive(i) != 0)
 			{
 				ch++;
 			}
 		}
 		BgDrawPrintf(1, 12, "Channel Active:%d", ch);
 
 
 		KeyExec();
 		u32 off = KeyGetOff();
 		u32 trg = KeyGetTrg();
 
 		if(trg & KEY_A) amb = mmEffectEx(&ambulance);
 		if(off & KEY_A)       mmEffectCancel(amb);
 
 		if(trg & KEY_B) mmEffectEx(&boom);
 		if(trg & KEY_L) mmStop();
 		if(trg & KEY_R) mmStart(MOD_FLATOUTLIES, MM_PLAY_LOOP);
 	}
 }

音楽データを加工するにはmakefileで以下のようにしています。maxmodのmmutil.exeと呼ばれる専用ツールがあるので、1つのバイナリデータに加工してくれます。

 soundbank.s : $(WAVFILES) $(MODFILES)
 	@echo \# converting $(WAVFILES) $(MODFILES)
 	@mmutil $^ -osoundbank.bin -hsoundbank.h
 	@bin2s soundbank.bin > $@

もしMaxModを扱うのでしたら[[Maxmod Programming Reference:https://maxmod.devkitpro.org/ref/]]は必読書になると思います。ページの後半が詳しいので読んでみてください。
もしMaxModを扱うのでしたら[[Maxmod Programming Reference:https://maxmod.devkitpro.org/ref/]]は必読書になると思います。ページ後半のGBA Programming Guideが詳しいので読んでみてください。

** 動作画面 [#u6e9c70b]
#ref(1.png,nolink)

** 履歴 [#gfa4226d]
- 2023/05/18

トップ   差分 履歴 リロード   一覧 検索 最終更新   ヘルプ   最終更新のRSS