/* ALICE SOFT SYSTEM 3 for Win32 [ MAKO ] */ #include #include #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, const char* playlist) : current_music(0), next_loop(0), nact(parent), mix_music(NULL), mix_chunk(NULL) { int mix_init_flags = MIX_INIT_MID; if (playlist && load_playlist(playlist)) mix_init_flags |= MIX_INIT_MP3 | MIX_INIT_OGG; _tcscpy_s(amus, 16, _T("AMUS.DAT")); _tcscpy_s(amse, 16, _T("AMSE.DAT")); // 実際には使わない for(int i = 1; i <= 99; i++) { cd_track[i] = 0; } if (Mix_Init(mix_init_flags) != mix_init_flags) WARNING("Mix_Init(0x%x) failed", mix_init_flags); if (Mix_OpenAudio(44100, AUDIO_S16LSB, 2, 4096) < 0) WARNING("Mix_OpenAudio failed: %s", Mix_GetError()); } MAKO::~MAKO() { stop_pcm(); Mix_CloseAudio(); Mix_Quit(); } bool MAKO::load_playlist(const char* path) { FILE* fp = fopen(path, "rt"); if (!fp) { WARNING("Cannot open %s", path); return false; } char buf[256]; while (fgets(buf, sizeof(buf) - 1, fp)) { char *p = &buf[strlen(buf) - 1]; if (*p == '\n') *p = '\0'; playlist.push_back(buf[0] ? strdup(buf) : NULL); } fclose(fp); return true; } void MAKO::play_music(int page) { if(current_music == page) return; stop_music(); int track = page < 100 ? cd_track[page] : 0; if(track) { if (track < playlist.size() && playlist[track]) { mix_music = Mix_LoadMUS(playlist[track]); if (!mix_music) { WARNING("Mix_LoadMUS failed: %s: %s", playlist[track], Mix_GetError()); return; } if (Mix_PlayMusic(mix_music, next_loop ? next_loop : -1) != 0) { WARNING("Mix_PlayMusic failed: %s", Mix_GetError()); Mix_FreeMusic(mix_music); return; } } } else { MAKOMidi midi(nact, amus); if (midi.load_mml(page)) { midi.load_mda(page); smf = midi.generate_smf(next_loop); 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()); Mix_FreeMusic(mix_music); return; } } } current_music = page; } void MAKO::stop_music() { if (mix_music) { Mix_FreeMusic(mix_music); mix_music = NULL; smf.clear(); } current_music = 0; } bool MAKO::check_music() { return Mix_PlayingMusic(); } void MAKO::get_mark(int* mark, int* loop) { // TODO: fix *mark = 0; *loop = 0; } void MAKO::play_pcm(int page, bool loop) { 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 }; stop_pcm(); uint8* buffer = NULL; int size; DRI* dri = new DRI(); if((buffer = dri->load(_T("AWAV.DAT"), page, &size)) != NULL) { // WAV形式 (Only You) mix_chunk = Mix_LoadWAV_RW(SDL_RWFromConstMem(buffer, size), 1 /* freesrc */); free(buffer); Mix_PlayChannel(-1, mix_chunk, loop ? -1 : 0); } else if((buffer = dri->load(_T("AMSE.DAT"), page, &size)) != NULL) { // AMSE形式 (乙女戦記) int total = (size - 12) * 2 + 0x24; int samples = (size - 12) * 2; uint8* wav = (uint8*)malloc(total + 8); 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; i++) { wav[p++] = buffer[i] & 0xf0; wav[p++] = (buffer[i] & 0x0f) << 4; } free(buffer); mix_chunk = Mix_LoadWAV_RW(SDL_RWFromConstMem(wav, total + 8), 1 /* freesrc */); free(wav); Mix_PlayChannel(-1, mix_chunk, loop ? -1 : 0); } } void MAKO::stop_pcm() { Mix_HaltChannel(-1); if (mix_chunk) { Mix_FreeChunk(mix_chunk); mix_chunk = NULL; } } bool MAKO::check_pcm() { // 再生中でtrue return Mix_Playing(-1) != 0; }