/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * $Id$ * * Copyright (C) 2005 by Magnus Holmgren * * All files in this archive are subject to the GNU General Public License. * See the file COPYING in the source tree root for full license agreement. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ****************************************************************************/ #include "autoconf.h" #ifdef ROCKBOX_HAS_SIMSOUND #define WINDOWS_LEAN_AND_MEAN #include #include #include #include #include "sound.h" #include "kernel.h" #include "thread-win32.h" #include "debug.h" void pcm_play_stop(void); static void sound_play_chunk(HWAVEOUT wave_out, LPWAVEHDR header, HANDLE event) { unsigned char* buf; long len; if (!(header->dwFlags & WHDR_DONE) || !sound_get_pcm) { return; } EnterCriticalSection(&CriticalSection); sound_get_pcm(&buf, &len); LeaveCriticalSection(&CriticalSection); if (len == 0) { DEBUGF("simulator got no pcm\n"); sound_get_pcm = NULL; return; } header->lpData = buf; header->dwBufferLength = len; header->dwBytesRecorded = 0; header->dwUser = 0; header->dwFlags = 0; header->dwLoops = 1; header->lpNext = NULL; header->reserved = 0; if (MMSYSERR_NOERROR != waveOutPrepareHeader(wave_out, header, sizeof(*header))) { return; } ResetEvent(event); waveOutWrite(wave_out, header, sizeof(*header)); } static int sound_init(LPHWAVEOUT wave_out, HANDLE event) { static const WAVEFORMATEX format = { WAVE_FORMAT_PCM, /* Format */ 2, /* Number of channels */ 44100, /* Samples per second */ 44100 * 4, /* Bytes per second */ 4, /* Block align */ 16, /* Bits per sample */ 0 /* Extra size */ }; if (MMSYSERR_NOERROR != waveOutOpen(wave_out, WAVE_MAPPER, &format, (DWORD_PTR) event, 0, CALLBACK_EVENT)) { return -1; } /* Full volume on left and right */ waveOutSetVolume(*wave_out, 0xffffffff); return 0; } void sound_playback_thread(void) { /* To get smooth playback, two buffers are needed, which are queued for * playback. (There can still be glitches though.) */ HWAVEOUT wave_out; WAVEHDR header1; WAVEHDR header2; HANDLE event; int result = -1; if ((event = CreateEvent(NULL, FALSE, FALSE, NULL))) { result = sound_init(&wave_out, event); } while(-1 == result || !event) { Sleep(100000); /* Wait forever, can't play sound! */ } while (true) { while (!sound_get_pcm) { /* TODO: fix a fine thread-synch mechanism here */ Sleep(100); } DEBUGF("starting simulator playback\n"); header1.dwFlags = WHDR_DONE; header2.dwFlags = WHDR_DONE; sound_play_chunk(wave_out, &header1, event); sound_play_chunk(wave_out, &header2, event); while (sound_get_pcm && (WAIT_FAILED != WaitForSingleObject(event, 1000))) { sound_play_chunk(wave_out, &header1, event); sound_play_chunk(wave_out, &header2, event); } pcm_play_stop(); DEBUGF("stopping simulator playback\n"); waveOutReset(wave_out); } } #endif /* ROCKBOX_HAS_SIMSOUND */