mirror of
https://github.com/kichikuou/system3-sdl2.git
synced 2026-09-29 02:18:09 +03:00
Instead of controlling MIDI device in real time, generate a data stream in SMF format and feed it to SDL_mixer.
224 lines
5.1 KiB
C++
224 lines
5.1 KiB
C++
/*
|
|
ALICE SOFT SYSTEM 3 for Win32
|
|
|
|
[ MAKO ]
|
|
*/
|
|
|
|
#include <SDL.h>
|
|
#include <SDL_mixer.h>
|
|
|
|
#include "mako.h"
|
|
#include "mako_midi.h"
|
|
#include "dri.h"
|
|
|
|
// MIX_INIT_FLUIDSYNTH was renamed to MIX_INIT_MID in SDL_mixer 2.0.2
|
|
#if (SDL_MIXER_MAJOR_VERSION == 2) && (SDL_MIXER_MINOR_VERSION == 0) && (SDL_MIXER_PATCHLEVEL < 2)
|
|
#define MIX_INIT_MID MIX_INIT_FLUIDSYNTH
|
|
#endif
|
|
|
|
MAKO::MAKO(NACT* parent) : nact(parent)
|
|
{
|
|
// AMUS.DAT, AMSE.DAT
|
|
_tcscpy_s(amus, 16, _T("AMUS.DAT"));
|
|
_tcscpy_s(amse, 16, _T("AMSE.DAT")); // 実際には使わない
|
|
|
|
// 再生状況
|
|
current_music = current_loop = 0;
|
|
current_max = next_loop = 0;
|
|
|
|
// CD-DA
|
|
for(int i = 1; i <= 99; i++) {
|
|
cd_track[i] = 0;
|
|
}
|
|
cdda_play = false;
|
|
if (Mix_Init(MIX_INIT_MID) != MIX_INIT_MID) {
|
|
WARNING("Mix_Init failed");
|
|
}
|
|
if (Mix_OpenAudio(44100, AUDIO_S16LSB, 2, 4096) < 0) {
|
|
WARNING("Mix_OpenAudio failed: %s", Mix_GetError());
|
|
}
|
|
}
|
|
|
|
MAKO::~MAKO()
|
|
{
|
|
Mix_CloseAudio();
|
|
Mix_Quit();
|
|
|
|
// PCM停止
|
|
#if defined(_USE_PCM)
|
|
PlaySound(NULL, NULL, SND_PURGE);
|
|
#endif
|
|
}
|
|
|
|
void MAKO::play_music(int page)
|
|
{
|
|
// 既に同じ曲を再生している
|
|
if(current_music == page) {
|
|
return;
|
|
}
|
|
|
|
stop_music();
|
|
|
|
current_music = page;
|
|
current_max = next_loop;
|
|
|
|
if(page < 100 && cd_track[page]) {
|
|
// CD-DAで再生
|
|
// TODO: fix
|
|
// PostMessage(g_hwnd, WM_USER, cd_track[page] + 1, 0);
|
|
cdda_play = true;
|
|
} else {
|
|
MAKOMidi midi(nact, amus);
|
|
if (midi.load_mml(page)) {
|
|
midi.load_mda(page);
|
|
smf = midi.generate_smf(current_max);
|
|
SDL_RWops *rwops = SDL_RWFromConstMem(smf.data(), smf.size());
|
|
mix_music = Mix_LoadMUSType_RW(rwops, MUS_MID, SDL_TRUE /* freesrc */);
|
|
if (!mix_music) {
|
|
WARNING("Mix_LoadMUS failed: %s", Mix_GetError());
|
|
return;
|
|
}
|
|
if (Mix_PlayMusic(mix_music, -1) != 0) {
|
|
WARNING("Mix_PlayMusic failed: %s", Mix_GetError());
|
|
return;
|
|
}
|
|
}
|
|
cdda_play = false;
|
|
}
|
|
}
|
|
|
|
void MAKO::stop_music()
|
|
{
|
|
// 現在再生中の場合は停止する
|
|
if(current_music) {
|
|
if(cdda_play) {
|
|
// TODO: fix
|
|
// PostMessage(g_hwnd, WM_USER, 0, 0);
|
|
} else {
|
|
if (mix_music) {
|
|
Mix_FreeMusic(mix_music);
|
|
mix_music = NULL;
|
|
smf.clear();
|
|
}
|
|
}
|
|
}
|
|
cdda_play = false;
|
|
current_music = current_loop = 0;
|
|
}
|
|
|
|
bool MAKO::check_music()
|
|
{
|
|
// 再生中でtrue
|
|
if (!current_music)
|
|
return false;
|
|
if (mix_music)
|
|
return Mix_PlayingMusic();
|
|
return true;
|
|
}
|
|
|
|
void MAKO::get_mark(int* mark, int* loop)
|
|
{
|
|
// TODO: fix
|
|
*mark = 0;
|
|
*loop = cdda_play ? 0 : current_loop;
|
|
}
|
|
|
|
void MAKO::notify_mci(int status)
|
|
{
|
|
if(status == -1) {
|
|
// 再生に失敗
|
|
current_music = current_loop = 0;
|
|
return;
|
|
}
|
|
|
|
if(cdda_play) {
|
|
current_loop++;
|
|
if(current_loop < current_max || current_max == 0) {
|
|
// TODO: fix
|
|
// PostMessage(g_hwnd, WM_USER, cd_track[current_music] + 1, 0);
|
|
} else {
|
|
current_music = current_loop = 0;
|
|
cdda_play = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
void MAKO::play_pcm(int page, bool loop)
|
|
{
|
|
assert(false);
|
|
#if defined(_USE_PCM)
|
|
static char header[44] = {
|
|
'R' , 'I' , 'F' , 'F' , 0x00, 0x00, 0x00, 0x00, 'W' , 'A' , 'V' , 'E' , 'f' , 'm' , 't' , ' ' ,
|
|
0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x40, 0x1f, 0x00, 0x00, 0x40, 0x1f, 0x00, 0x00,
|
|
0x01, 0x00, 0x08, 0x00, 'd' , 'a' , 't' , 'a' , 0x00, 0x00, 0x00, 0x00
|
|
};
|
|
|
|
// 現在再生中のPCMを停止
|
|
PlaySound(NULL, NULL, SND_PURGE);
|
|
|
|
uint8* buffer = NULL;
|
|
int size;
|
|
DRI* dri = new DRI();
|
|
|
|
if((buffer = dri->load(_T("AWAV.DAT"), page, &size)) != NULL) {
|
|
// WAV形式 (Only You)
|
|
memcpy(wav, buffer, (size < MAX_SAMPLES) ? size : MAX_SAMPLES);
|
|
|
|
if(loop) {
|
|
PlaySound(wav, NULL, SND_ASYNC | SND_MEMORY | SND_LOOP);
|
|
} else {
|
|
PlaySound(wav, NULL, SND_ASYNC | SND_MEMORY);
|
|
}
|
|
free(buffer);
|
|
} else if((buffer = dri->load(_T("AMSE.DAT"), page, &size)) != NULL) {
|
|
// AMSE形式 (乙女戦記)
|
|
int total = (size - 12) * 2 + 0x24;
|
|
int samples = (size - 12) * 2;
|
|
|
|
memcpy(wav, header, 44);
|
|
wav[ 4] = (total >> 0) & 0xff;
|
|
wav[ 5] = (total >> 8) & 0xff;
|
|
wav[ 6] = (total >> 16) & 0xff;
|
|
wav[ 7] = (total >> 24) & 0xff;
|
|
wav[40] = (samples >> 0) & 0xff;
|
|
wav[41] = (samples >> 8) & 0xff;
|
|
wav[42] = (samples >> 16) & 0xff;
|
|
wav[43] = (samples >> 24) & 0xff;
|
|
for(int i = 12, p = 44; i < size && p < MAX_SAMPLES - 2; i++) {
|
|
wav[p++] = buffer[i] & 0xf0;
|
|
wav[p++] = (buffer[i] & 0x0f) << 4;
|
|
}
|
|
|
|
if(loop) {
|
|
PlaySound(wav, NULL, SND_ASYNC | SND_MEMORY | SND_LOOP);
|
|
} else {
|
|
PlaySound(wav, NULL, SND_ASYNC | SND_MEMORY);
|
|
}
|
|
free(buffer);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void MAKO::stop_pcm()
|
|
{
|
|
#if defined(_USE_PCM)
|
|
PlaySound(NULL, NULL, SND_PURGE);
|
|
#endif
|
|
}
|
|
|
|
bool MAKO::check_pcm()
|
|
{
|
|
// 再生中でtrue
|
|
#if defined(_USE_PCM)
|
|
static char null_wav[45] = {
|
|
'R' , 'I' , 'F' , 'F' , 0x25, 0x00, 0x00, 0x00, 'W' , 'A' , 'V' , 'E' , 'f' , 'm' , 't' , ' ' ,
|
|
0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x40, 0x1f, 0x00, 0x00, 0x40, 0x1f, 0x00, 0x00,
|
|
0x01, 0x00, 0x08, 0x00, 'd' , 'a' , 't' , 'a' , 0x01, 0x00, 0x00, 0x00, 0x00
|
|
};
|
|
return PlaySound(null_wav, NULL, SND_ASYNC | SND_MEMORY | SND_NOSTOP) ? false : true;
|
|
#else
|
|
return false;
|
|
#endif
|
|
}
|
|
|