RString RageSoundDriver_WaveOut::Init() { m_iSampleRate = PREFSMAN->m_iSoundPreferredSampleRate; if( m_iSampleRate == 0 ) m_iSampleRate = 44100; WAVEFORMATEX fmt; fmt.wFormatTag = WAVE_FORMAT_PCM; fmt.nChannels = channels; fmt.cbSize = 0; fmt.nSamplesPerSec = m_iSampleRate; fmt.wBitsPerSample = 16; fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8; fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign; MMRESULT ret = waveOutOpen( &m_hWaveOut, WAVE_MAPPER, &fmt, (DWORD_PTR) m_hSoundEvent, NULL, CALLBACK_EVENT ); if( ret != MMSYSERR_NOERROR ) return wo_ssprintf( ret, "waveOutOpen failed" ); ZERO( m_aBuffers ); for(int b = 0; b < num_chunks; ++b) { m_aBuffers[b].dwBufferLength = chunksize; m_aBuffers[b].lpData = new char[chunksize]; ret = waveOutPrepareHeader( m_hWaveOut, &m_aBuffers[b], sizeof(m_aBuffers[b]) ); if( ret != MMSYSERR_NOERROR ) return wo_ssprintf( ret, "waveOutPrepareHeader failed" ); m_aBuffers[b].dwFlags |= WHDR_DONE; } LOG->Info( "WaveOut software mixing at %i hz", m_iSampleRate ); /* We have a very large writeahead; make sure we have a large enough decode * buffer to recover cleanly from underruns. */ SetDecodeBufferSize( buffersize_frames * 3/2 ); StartDecodeThread(); MixingThread.SetName( "Mixer thread" ); MixingThread.Create( MixerThread_start, this ); return RString(); }
static void GetSoundDriverDebugInfo() { int cnt = waveOutGetNumDevs(); for(int i = 0; i < cnt; ++i) { WAVEOUTCAPS caps; MMRESULT ret = waveOutGetDevCaps(i, &caps, sizeof(caps)); if(ret != MMSYSERR_NOERROR) { LOG->Info(wo_ssprintf(ret, "waveOutGetDevCaps(%i) failed", i)); continue; } LOG->Info("Sound device %i: %s, %i.%i, MID %i, PID %i %s", i, caps.szPname, HIBYTE(caps.vDriverVersion), LOBYTE(caps.vDriverVersion), caps.wMid, caps.wPid, caps.dwSupport & WAVECAPS_SAMPLEACCURATE? "":"(INACCURATE)"); } }
bool RageSoundDriver_WaveOut::GetData() { /* Look for a free buffer. */ int b; for( b = 0; b < num_chunks; ++b ) if( m_aBuffers[b].dwFlags & WHDR_DONE ) break; if( b == num_chunks ) return false; /* Call the callback. */ this->Mix( (int16_t *) m_aBuffers[b].lpData, chunksize_frames, m_iLastCursorPos, GetPosition() ); MMRESULT ret = waveOutWrite( m_hWaveOut, &m_aBuffers[b], sizeof(m_aBuffers[b]) ); if( ret != MMSYSERR_NOERROR ) FAIL_M( wo_ssprintf(ret, "waveOutWrite failed") ); /* Increment m_iLastCursorPos. */ m_iLastCursorPos += chunksize_frames; return true; }
int64_t RageSoundDriver_WaveOut::GetPosition() const { MMTIME tm; tm.wType = TIME_SAMPLES; MMRESULT ret = waveOutGetPosition( m_hWaveOut, &tm, sizeof(tm) ); if( ret != MMSYSERR_NOERROR ) FAIL_M( wo_ssprintf(ret, "waveOutGetPosition failed") ); return tm.u.sample; }