- 追加された行はこの色です。
- 削除された行はこの色です。
#author("2023-05-19T13:54:19+09:00;2023-05-18T13:21:02+09:00","","")
#freeze
#author("2023-05-30T11:06:27+09:00","","")
* DirectSound2 [#bf4bc923]
singed 8bitは素のデータ構造であって、保存形式としては全然向いていません。もし30分の音楽データを入れたいなと思った場合は30分*60秒=1800秒、1800*16384バイト=29,491,200バイトとなって圧迫感が半端ないです。そこで圧縮しつつもCPU使用率を取らないライブラリを紹介します。
音楽データの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に標準装備されていて非常に有名です。数少ないdevkitProのexamplesプログラムの1つです。libmm.aを組み込みも方法となるmakefileもあるので簡単な方ではあります。MOD, S3M, XM, and ITとwavも対応しています。
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.
MOD playing routines and support for up to 16 channels.
** Krawall [#x576fed7]
https://github.com/sebknzl/krawall~
詳しくは不明です。XM/S3M Modplayer.
XM/S3M Modplayer.
** GBT Player [#j68677c7]
https://github.com/AntonioND/gbt-player~
DirectSoundと関係ないですけれどゲームボーイサウンドとして有名です。詳しくは不明です。
* ところでMod多くない? [#xd081c74]
個人的にはmidiの方が親しみを持つのですけれど、midiフォーマットですとGBサウンドの仕様を満たすのは難しいようです。modトラッカー使った方がツールも豊富です。以下に、MaxModのサンプルプログラムを用意しました。libmm.aを組み込むだけですとdevkitproのサンプルと被るので、MaxModソースコードを直接コンパイルして、libgccもお世話にならない作りにしました。
** ところでMod多くない? [#xd081c74]
海外圏はmidi文化ではなくmod文化の為、ということなんだと個人的に解釈しています。まーしょうがないですよ。mod編集エディタで作る方が簡単だと思います。ここではMaxModのサンプルプログラムを用意しました。libmm.aを組み込むだけですと味気ないので、MaxModソースコードをコンパイルして、libgccもお世話にならない作りをしています。
** MaxModのコンパイルメモ [#z0fc8c51]
- 1.ASFLAGS~
ASFLAGSにSYS_GBAを組み込みます。*.sファイルに多量にDS用かGBA用かの判定がある為です。
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当てています。
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バイトでした。
- 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}, (int)(1.0f * (1<<10)), 0, 255, 0 };
mm_sound_effect boom = { {SFX_BOOM}, (int)(1.0f * (1<<10)), 0, 255, 255 };
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で以下のようにするといいと思います。mmutil.exeと呼ばれる専用ツールが使われています。
音楽データを加工するには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/]]は必読書になると思います。ページ後半のGBA Programming Guideが詳しいので読んでみてください。
** 動作画面 [#u6e9c70b]
#ref(1.png,nolink)
** 履歴 [#gfa4226d]
- 2023/05/18