From 5cc00db3c77d58478ed1d2e96c226dfbfdd0d0a2 Mon Sep 17 00:00:00 2001 From: "fbarchard@chromium.org" Date: Mon, 18 Oct 2010 18:25:07 +0000 Subject: add wave out extensible support for 5.1 surround sound BUG=25315 TEST=play 5.1 audio and it should come out all 6 speakers, not downmixed to stereo. Review URL: http://codereview.chromium.org/3772009 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@62954 0039d316-1c4b-4281-b951-d872f2087c98 --- media/audio/win/waveout_output_win.cc | 49 +++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 16 deletions(-) (limited to 'media/audio/win/waveout_output_win.cc') diff --git a/media/audio/win/waveout_output_win.cc b/media/audio/win/waveout_output_win.cc index 03da37d..0865477 100644 --- a/media/audio/win/waveout_output_win.cc +++ b/media/audio/win/waveout_output_win.cc @@ -55,14 +55,28 @@ PCMWaveOutAudioOutputStream::PCMWaveOutAudioOutputStream( volume_(1), channels_(params.channels), pending_bytes_(0) { - format_.wFormatTag = WAVE_FORMAT_PCM; - format_.nChannels = params.channels > 2 ? 2 : params.channels; - format_.nSamplesPerSec = params.sample_rate; - format_.wBitsPerSample = params.bits_per_sample; - format_.cbSize = 0; + format_.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; + format_.Format.nChannels = params.channels; + format_.Format.nSamplesPerSec = params.sample_rate; + format_.Format.wBitsPerSample = params.bits_per_sample; + format_.Format.cbSize = sizeof(format_) - sizeof(WAVEFORMATEX); // The next are computed from above. - format_.nBlockAlign = (format_.nChannels * format_.wBitsPerSample) / 8; - format_.nAvgBytesPerSec = format_.nBlockAlign * format_.nSamplesPerSec; + format_.Format.nBlockAlign = (format_.Format.nChannels * + format_.Format.wBitsPerSample) / 8; + format_.Format.nAvgBytesPerSec = format_.Format.nBlockAlign * + format_.Format.nSamplesPerSec; + // This mask handles Stereo, 5.1 and 7.1. + // TODO(fbarchard): Support masks for other channel layouts. + format_.dwChannelMask = SPEAKER_FRONT_LEFT | + SPEAKER_FRONT_RIGHT | + SPEAKER_FRONT_CENTER | + SPEAKER_LOW_FREQUENCY | + SPEAKER_BACK_LEFT | + SPEAKER_BACK_RIGHT | + SPEAKER_SIDE_LEFT | + SPEAKER_SIDE_RIGHT; + format_.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + format_.Samples.wValidBitsPerSample = params.bits_per_sample; // The event is auto-reset. stopped_event_.Set(::CreateEventW(NULL, FALSE, FALSE, NULL)); } @@ -78,9 +92,10 @@ bool PCMWaveOutAudioOutputStream::Open(uint32 buffer_size) { return false; if (num_buffers_ < 2 || num_buffers_ > 5) return false; - // Open the device. We'll be getting callback in WaveCallback function. They - // occur in a magic, time-critical thread that windows creates. - MMRESULT result = ::waveOutOpen(&waveout_, device_id_, &format_, + // Open the device. We'll be getting callback in WaveCallback function. + // They occur in a magic, time-critical thread that windows creates. + MMRESULT result = ::waveOutOpen(&waveout_, device_id_, + reinterpret_cast(&format_), reinterpret_cast(WaveCallback), reinterpret_cast(this), CALLBACK_FUNCTION); @@ -88,7 +103,7 @@ bool PCMWaveOutAudioOutputStream::Open(uint32 buffer_size) { return false; // If we don't have a packet size we use 100ms. if (!buffer_size) - buffer_size = format_.nAvgBytesPerSec / 10; + buffer_size = format_.Format.nAvgBytesPerSec / 10; SetupBuffers(buffer_size); buffer_size_ = buffer_size; @@ -235,20 +250,22 @@ void PCMWaveOutAudioOutputStream::QueueNextPacket(WAVEHDR *buffer) { // If we are down sampling to a smaller number of channels, we need to // scale up the amount of pending bytes. // TODO(fbarchard): Handle used 0 by queueing more. - uint32 scaled_pending_bytes = pending_bytes_ * channels_ / format_.nChannels; + uint32 scaled_pending_bytes = pending_bytes_ * channels_ / + format_.Format.nChannels; // TODO(sergeyu): Specify correct hardware delay for AudioBuffersState. uint32 used = callback_->OnMoreData( this, reinterpret_cast(buffer->lpData), buffer_size_, AudioBuffersState(scaled_pending_bytes, 0)); if (used <= buffer_size_) { - buffer->dwBufferLength = used * format_.nChannels / channels_; - if (channels_ > 2 && format_.nChannels == 2) { + buffer->dwBufferLength = used * format_.Format.nChannels / channels_; + if (channels_ > 2 && format_.Format.nChannels == 2) { media::FoldChannels(buffer->lpData, used, - channels_, format_.wBitsPerSample >> 3, + channels_, format_.Format.wBitsPerSample >> 3, volume_); } else { media::AdjustVolume(buffer->lpData, used, - format_.nChannels, format_.wBitsPerSample >> 3, + format_.Format.nChannels, + format_.Format.wBitsPerSample >> 3, volume_); } } else { -- cgit v1.1