From: <man...@us...> - 2013-08-11 17:33:18
|
Revision: 2599 http://sourceforge.net/p/modplug/code/2599 Author: manxorist Date: 2013-08-11 17:33:10 +0000 (Sun, 11 Aug 2013) Log Message: ----------- [Ref] Replace inline asm sample conversion functions in CASIODevice with c++ implementation from SampleFormatConverters.h . [Mod] CASIODevice used 16bit or 32bit sample input and converted it to the sample format requested by the ASIO driver. Remove 16bit integer support and add 32bit floating point support instead. This removes dithering for 16bit ASIO devices for now (which should be a really really rare configuration anyway). [Mod] Display sample format used for sending data to CASIODevice in soundcard options dialog and disable the combo box for ASIO devices because the user has no choice here anyway. [Ref] Make CASIODevice::FillAudioBuffer() more readable. Modified Paths: -------------- trunk/OpenMPT/mptrack/MainFrm.cpp trunk/OpenMPT/mptrack/Mpdlgs.cpp trunk/OpenMPT/sounddev/SoundDevice.cpp trunk/OpenMPT/sounddev/SoundDevice.h trunk/OpenMPT/sounddev/SoundDevices.h trunk/OpenMPT/soundlib/SampleFormatConverters.h Modified: trunk/OpenMPT/mptrack/MainFrm.cpp =================================================================== --- trunk/OpenMPT/mptrack/MainFrm.cpp 2013-08-11 00:18:18 UTC (rev 2598) +++ trunk/OpenMPT/mptrack/MainFrm.cpp 2013-08-11 17:33:10 UTC (rev 2599) @@ -945,9 +945,9 @@ SampleFormat fixedBitsPerSample = SampleFormatInvalid; { Util::lock_guard<Util::mutex> lock(m_SoundDeviceMutex); - fixedBitsPerSample = (gpSoundDevice) ? SampleFormat(gpSoundDevice->HasFixedBitsPerSample()) : SampleFormatInvalid; + fixedBitsPerSample = (gpSoundDevice) ? SampleFormat(gpSoundDevice->HasFixedSampleFormat()) : SampleFormatInvalid; } - if(err && (fixedBitsPerSample.IsValid() && (fixedBitsPerSample != TrackerSettings::Instance().m_SampleFormat))) + if(fixedBitsPerSample.IsValid() && (fixedBitsPerSample != TrackerSettings::Instance().m_SampleFormat)) { TrackerSettings::Instance().m_SampleFormat = fixedBitsPerSample; err = !audioTryOpeningDevice(TrackerSettings::Instance().m_MixerSettings.gnChannels, Modified: trunk/OpenMPT/mptrack/Mpdlgs.cpp =================================================================== --- trunk/OpenMPT/mptrack/Mpdlgs.cpp 2013-08-11 00:18:18 UTC (rev 2598) +++ trunk/OpenMPT/mptrack/Mpdlgs.cpp 2013-08-11 17:33:10 UTC (rev 2599) @@ -287,37 +287,43 @@ void COptionsSoundcard::UpdateSampleFormat(int dev) //------------------------------------------------- { - CHAR s[128]; UINT n = 0; m_CbnSampleFormat.ResetContent(); - for(UINT bits = 32; bits >= 8; bits -= 8) + const bool asio = SNDDEV_GET_TYPE(dev) == SNDDEV_ASIO; + if(asio) { - if(bits > 16 && !theApp.IsWaveExEnabled() && SNDDEV_GET_TYPE(dev) != SNDDEV_ASIO) + m_SampleFormat = TrackerSettings::Instance().m_SampleFormat; + } + m_CbnSampleFormat.EnableWindow(asio ? FALSE : TRUE); + for(UINT bits = 40; bits >= 8; bits -= 8) + { + if(bits > 16 && !theApp.IsWaveExEnabled() && !asio) { continue; } - if(bits != 16 && bits != 32 && SNDDEV_GET_TYPE(dev) == SNDDEV_ASIO) + if(bits == 40) { - // CASIODevice only supports 16bit or 32bit input for now - continue; - } - if(bits == 32 && SNDDEV_GET_TYPE(dev) != SNDDEV_ASIO) + if(!asio || (asio && SampleFormatFloat32 == m_SampleFormat)) + { + UINT ndx = m_CbnSampleFormat.AddString("Floating Point"); + m_CbnSampleFormat.SetItemData(ndx, (32+128)); + if(SampleFormatFloat32 == m_SampleFormat) + { + n = ndx; + } + } + } else { - wsprintf(s, "Floating Point"); - UINT ndx = m_CbnSampleFormat.AddString(s); - m_CbnSampleFormat.SetItemData(ndx, (32+128)); - if(SampleFormatFloat32 == m_SampleFormat) + if(!asio || (asio && (SampleFormat)bits == m_SampleFormat)) { - n = ndx; + UINT ndx = m_CbnSampleFormat.AddString(mpt::String::Format("%d Bit", bits).c_str()); + m_CbnSampleFormat.SetItemData(ndx, bits); + if((SampleFormat)bits == m_SampleFormat) + { + n = ndx; + } } } - wsprintf(s, "%d Bit", bits); - UINT ndx = m_CbnSampleFormat.AddString(s); - m_CbnSampleFormat.SetItemData(ndx, bits); - if((SampleFormat)bits == m_SampleFormat) - { - n = ndx; - } } m_CbnSampleFormat.SetCurSel(n); } @@ -538,6 +544,7 @@ m_CbnUpdateIntervalMS.SetWindowText(s); } CMainFrame::GetMainFrame()->SetupSoundCard(m_SoundDeviceFlags, m_dwRate, m_SampleFormat, m_nChannels, m_LatencyMS, m_UpdateIntervalMS, m_nSoundDevice); + UpdateSampleFormat(m_nSoundDevice); UpdateStatistics(); CPropertyPage::OnOK(); } Modified: trunk/OpenMPT/sounddev/SoundDevice.cpp =================================================================== --- trunk/OpenMPT/sounddev/SoundDevice.cpp 2013-08-11 00:18:18 UTC (rev 2598) +++ trunk/OpenMPT/sounddev/SoundDevice.cpp 2013-08-11 17:33:10 UTC (rev 2599) @@ -18,6 +18,8 @@ #include "../mptrack/Reporting.h" #endif #include "../common/StringFixer.h" +struct ModSample; +#include "../soundlib/SampleFormatConverters.h" // DEBUG: #include "../common/AudioCriticalSection.h" @@ -1212,11 +1214,14 @@ //------------------------ { m_pAsioDrv = NULL; + m_nChannels = 0; + m_nAsioBufferLen = 0; + m_nAsioSampleSize = 0; + m_Float = false; m_Callbacks.bufferSwitch = BufferSwitch; m_Callbacks.sampleRateDidChange = SampleRateDidChange; m_Callbacks.asioMessage = AsioMessage; m_Callbacks.bufferSwitchTimeInfo = BufferSwitchTimeInfo; - m_nBitsPerSample = 0; // Unknown m_nCurrentDevice = (ULONG)-1; m_bMixRunning = FALSE; InterlockedExchange(&m_RenderSilence, 0); @@ -1245,7 +1250,6 @@ if (nDevice != m_nCurrentDevice) { m_nCurrentDevice = nDevice; - m_nBitsPerSample = 0; } #ifdef ASIO_LOG Log("CASIODevice::Open(%d:\"%s\"): %d-bit, %d channels, %dHz\n", @@ -1273,7 +1277,6 @@ #endif goto abort; } - m_nBitsPerSample = m_Settings.BitsPerSample; for (UINT ich=0; ich<m_Settings.Channels; ich++) { m_ChannelInfo[ich].channel = ich; @@ -1287,28 +1290,50 @@ m_BufferInfo[ich].channelNum = ich + CASIODevice::baseChannel; // map MPT channel i to ASIO channel i m_BufferInfo[ich].buffers[0] = NULL; m_BufferInfo[ich].buffers[1] = NULL; - if ((m_ChannelInfo[ich].type & 0x0f) == ASIOSTInt16MSB) + if(m_Settings.BitsPerSample != 32 && m_Settings.BitsPerSample != 32+128) { - if (m_nBitsPerSample < 16) - { - m_nBitsPerSample = 16; - goto abort; - } - } else + goto abort; + } + m_Float = false; + switch(m_ChannelInfo[ich].type) { - if (m_nBitsPerSample != 32) - { - m_nBitsPerSample = 32; + case ASIOSTInt16MSB: + case ASIOSTInt16LSB: + m_nAsioSampleSize = 2; + break; + case ASIOSTInt24MSB: + case ASIOSTInt24LSB: + m_nAsioSampleSize = 3; + break; + case ASIOSTInt32MSB: + case ASIOSTInt32LSB: + m_nAsioSampleSize = 4; + break; + case ASIOSTInt32MSB16: + case ASIOSTInt32MSB18: + case ASIOSTInt32MSB20: + case ASIOSTInt32MSB24: + case ASIOSTInt32LSB16: + case ASIOSTInt32LSB18: + case ASIOSTInt32LSB20: + case ASIOSTInt32LSB24: + m_nAsioSampleSize = 4; + break; + case ASIOSTFloat32MSB: + case ASIOSTFloat32LSB: + m_Float = true; + m_nAsioSampleSize = 4; + break; + case ASIOSTFloat64MSB: + case ASIOSTFloat64LSB: + m_Float = true; + m_nAsioSampleSize = 8; + break; + default: + m_nAsioSampleSize = 0; goto abort; - } + break; } - switch(m_ChannelInfo[ich].type & 0x0f) - { - case ASIOSTInt16MSB: m_nAsioSampleSize = 2; break; - case ASIOSTInt24MSB: m_nAsioSampleSize = 3; break; - case ASIOSTFloat64MSB: m_nAsioSampleSize = 8; break; - default: m_nAsioSampleSize = 4; - } } m_pAsioDrv->getBufferSize(&minSize, &maxSize, &preferredSize, &granularity); #ifdef ASIO_LOG @@ -1561,105 +1586,126 @@ } } + +static void SwapEndian(uint8 *buf, std::size_t itemCount, std::size_t itemSize) +//----------------------------------------------------------------------------- +{ + for(std::size_t i = 0; i < itemCount; ++i) + { + std::reverse(buf, buf + itemSize); + buf += itemSize; + } +} + + void CASIODevice::FillAudioBuffer() //--------------------------------- { bool rendersilence = (InterlockedExchangeAdd(&m_RenderSilence, 0) == 1); - DWORD dwSampleSize = m_nChannels*(m_nBitsPerSample>>3); - DWORD dwSamplesLeft = m_nAsioBufferLen; - DWORD dwFrameLen = (ASIO_BLOCK_LEN*sizeof(int)) / dwSampleSize; - DWORD dwBufferOffset = 0; + std::size_t sampleFrameSize = m_nChannels * sizeof(int32); + const std::size_t sampleFramesGoal = m_nAsioBufferLen; + std::size_t sampleFramesToRender = sampleFramesGoal; + std::size_t sampleFramesRendered = 0; + const std::size_t countChunkMax = (ASIO_BLOCK_LEN * sizeof(int32)) / sampleFrameSize; g_dwBuffer &= 1; - //Log("FillAudioBuffer(%d): dwSampleSize=%d dwSamplesLeft=%d dwFrameLen=%d\n", g_dwBuffer, dwSampleSize, dwSamplesLeft, dwFrameLen); - while ((LONG)dwSamplesLeft > 0) + //Log("FillAudioBuffer(%d): dwSampleSize=%d dwSamplesLeft=%d dwFrameLen=%d\n", g_dwBuffer, sampleFrameSize, dwSamplesLeft, dwFrameLen); + while(sampleFramesToRender > 0) { - UINT n = (dwSamplesLeft < dwFrameLen) ? dwSamplesLeft : dwFrameLen; + const std::size_t countChunk = std::min(sampleFramesToRender, countChunkMax); if(rendersilence) { - memset(m_FrameBuffer, 0, n*dwSampleSize); + memset(m_FrameBuffer, 0, countChunk * sampleFrameSize); } else { - SourceAudioRead(m_FrameBuffer, n); + SourceAudioRead(m_FrameBuffer, countChunk); } - dwSamplesLeft -= n; - for (UINT ich=0; ich<m_nChannels; ich++) + for(int channel = 0; channel < (int)m_nChannels; ++channel) { - char *psrc = (char *)m_FrameBuffer; - char *pbuffer = (char *)m_BufferInfo[ich].buffers[g_dwBuffer]; - switch(m_ChannelInfo[ich].type) + const int32 *src = m_FrameBuffer; + const float *srcFloat = reinterpret_cast<const float*>(m_FrameBuffer); + void *dst = (char*)m_BufferInfo[channel].buffers[g_dwBuffer] + m_nAsioSampleSize * sampleFramesRendered; + if(m_Float) switch(m_ChannelInfo[channel].type) { - case ASIOSTInt16MSB: - if (m_nBitsPerSample == 32) - Cvt32To16msb(pbuffer+dwBufferOffset*2, psrc+ich*4, m_nChannels*4, n); - else - Cvt16To16msb(pbuffer+dwBufferOffset*2, psrc+ich*2, m_nChannels*2, n); - break; - case ASIOSTInt16LSB: - if (m_nBitsPerSample == 32) - Cvt32To16(pbuffer+dwBufferOffset*2, psrc+ich*4, m_nChannels*4, n); - else - Cvt16To16(pbuffer+dwBufferOffset*2, psrc+ich*2, m_nChannels*2, n); - break; - case ASIOSTInt24MSB: - Cvt32To24msb(pbuffer+dwBufferOffset*3, psrc+ich*4, m_nChannels*4, n); - break; - case ASIOSTInt24LSB: - Cvt32To24(pbuffer+dwBufferOffset*3, psrc+ich*4, m_nChannels*4, n); - break; - case ASIOSTInt32MSB: - Cvt32To32msb(pbuffer+dwBufferOffset*4, psrc+ich*4, m_nChannels*4, n, 0); - break; - case ASIOSTInt32LSB: - Cvt32To32(pbuffer+dwBufferOffset*4, psrc+ich*4, m_nChannels*4, n, 0); - break; - case ASIOSTFloat32MSB: - Cvt32To32f(pbuffer+dwBufferOffset*4, psrc+ich*4, m_nChannels*4, n); - EndianSwap32(pbuffer+dwBufferOffset*4, n); - break; - case ASIOSTFloat32LSB: - Cvt32To32f(pbuffer+dwBufferOffset*4, psrc+ich*4, m_nChannels*4, n); - break; - case ASIOSTFloat64MSB: - Cvt32To64f(pbuffer+dwBufferOffset*8, psrc+ich*4, m_nChannels*4, n); - EndianSwap64(pbuffer+dwBufferOffset*4, n); - break; - case ASIOSTFloat64LSB: - Cvt32To64f(pbuffer+dwBufferOffset*8, psrc+ich*4, m_nChannels*4, n); - break; - case ASIOSTInt32MSB16: - Cvt32To32msb(pbuffer+dwBufferOffset*4, psrc+ich*4, m_nChannels*4, n, 16); - break; - case ASIOSTInt32LSB16: - Cvt32To32(pbuffer+dwBufferOffset*4, psrc+ich*4, m_nChannels*4, n, 16); - break; - case ASIOSTInt32MSB18: - Cvt32To32msb(pbuffer+dwBufferOffset*4, psrc+ich*4, m_nChannels*4, n, 14); - break; - case ASIOSTInt32LSB18: - Cvt32To32(pbuffer+dwBufferOffset*4, psrc+ich*4, m_nChannels*4, n, 14); - break; - case ASIOSTInt32MSB20: - Cvt32To32msb(pbuffer+dwBufferOffset*4, psrc+ich*4, m_nChannels*4, n, 12); - break; - case ASIOSTInt32LSB20: - Cvt32To32(pbuffer+dwBufferOffset*4, psrc+ich*4, m_nChannels*4, n, 12); - break; - case ASIOSTInt32MSB24: - Cvt32To32msb(pbuffer+dwBufferOffset*4, psrc+ich*4, m_nChannels*4, n, 8); - break; - case ASIOSTInt32LSB24: - Cvt32To32(pbuffer+dwBufferOffset*4, psrc+ich*4, m_nChannels*4, n, 8); - break; + case ASIOSTFloat32MSB: + case ASIOSTFloat32LSB: + CopyInterleavedToChannel<SC::Convert<float, float> >(reinterpret_cast<float*>(dst), srcFloat, m_nChannels, countChunk, channel); + break; + case ASIOSTFloat64MSB: + case ASIOSTFloat64LSB: + CopyInterleavedToChannel<SC::Convert<double, float> >(reinterpret_cast<double*>(dst), srcFloat, m_nChannels, countChunk, channel); + break; + default: + ASSERT(false); + break; + } else switch(m_ChannelInfo[channel].type) + { + case ASIOSTInt16MSB: + case ASIOSTInt16LSB: + CopyInterleavedToChannel<SC::Convert<int16, int32> >(reinterpret_cast<int16*>(dst), src, m_nChannels, countChunk, channel); + break; + case ASIOSTInt24MSB: + case ASIOSTInt24LSB: + CopyInterleavedToChannel<SC::Convert<int24, int32> >(reinterpret_cast<int24*>(dst), src, m_nChannels, countChunk, channel); + break; + case ASIOSTInt32MSB: + case ASIOSTInt32LSB: + CopyInterleavedToChannel<SC::Convert<int32, int32> >(reinterpret_cast<int32*>(dst), src, m_nChannels, countChunk, channel); + break; + case ASIOSTFloat32MSB: + case ASIOSTFloat32LSB: + CopyInterleavedToChannel<SC::Convert<float, int32> >(reinterpret_cast<float*>(dst), src, m_nChannels, countChunk, channel); + break; + case ASIOSTFloat64MSB: + case ASIOSTFloat64LSB: + CopyInterleavedToChannel<SC::Convert<double, int32> >(reinterpret_cast<double*>(dst), src, m_nChannels, countChunk, channel); + break; + case ASIOSTInt32MSB16: + case ASIOSTInt32LSB16: + CopyInterleavedToChannel<SC::ConvertShift<int32, int32, 16> >(reinterpret_cast<int32*>(dst), src, m_nChannels, countChunk, channel); + break; + case ASIOSTInt32MSB18: + case ASIOSTInt32LSB18: + CopyInterleavedToChannel<SC::ConvertShift<int32, int32, 14> >(reinterpret_cast<int32*>(dst), src, m_nChannels, countChunk, channel); + break; + case ASIOSTInt32MSB20: + case ASIOSTInt32LSB20: + CopyInterleavedToChannel<SC::ConvertShift<int32, int32, 12> >(reinterpret_cast<int32*>(dst), src, m_nChannels, countChunk, channel); + break; + case ASIOSTInt32MSB24: + case ASIOSTInt32LSB24: + CopyInterleavedToChannel<SC::ConvertShift<int32, int32, 8> >(reinterpret_cast<int32*>(dst), src, m_nChannels, countChunk, channel); + break; + default: + ASSERT(false); + break; } + switch(m_ChannelInfo[channel].type) + { + case ASIOSTInt16MSB: + case ASIOSTInt24MSB: + case ASIOSTInt32MSB: + case ASIOSTFloat32MSB: + case ASIOSTFloat64MSB: + case ASIOSTInt32MSB16: + case ASIOSTInt32MSB18: + case ASIOSTInt32MSB20: + case ASIOSTInt32MSB24: + SwapEndian(reinterpret_cast<uint8*>(dst), countChunk, m_nAsioSampleSize); + break; + } } - dwBufferOffset += n; + sampleFramesToRender -= countChunk; + sampleFramesRendered += countChunk; } - if (m_bPostOutput) m_pAsioDrv->outputReady(); + if(m_bPostOutput) + { + m_pAsioDrv->outputReady(); + } if(!rendersilence) { - SourceAudioDone(dwBufferOffset, m_nAsioBufferLen); + SourceAudioDone(sampleFramesRendered, m_nAsioBufferLen); } return; } @@ -1727,258 +1773,6 @@ } -void CASIODevice::EndianSwap64(void *pbuffer, UINT nSamples) -//---------------------------------------------------------- -{ - _asm { - mov edx, pbuffer - mov ecx, nSamples -swaploop: - mov eax, dword ptr [edx] - mov ebx, dword ptr [edx+4] - add edx, 8 - bswap eax - bswap ebx - dec ecx - mov dword ptr [edx-8], ebx - mov dword ptr [edx-4], eax - jnz swaploop - } -} - - -void CASIODevice::EndianSwap32(void *pbuffer, UINT nSamples) -//---------------------------------------------------------- -{ - _asm { - mov edx, pbuffer - mov ecx, nSamples -swaploop: - mov eax, dword ptr [edx] - add edx, 4 - bswap eax - dec ecx - mov dword ptr [edx-4], eax - jnz swaploop - } -} - - -void CASIODevice::Cvt16To16(void *pdst, void *psrc, UINT nSampleSize, UINT nSamples) -//---------------------------------------------------------------------------------- -{ - _asm { - mov ebx, psrc - mov edi, pdst - mov esi, nSampleSize - mov ecx, nSamples -cvtloop: - movsx eax, word ptr [ebx] - add ebx, esi - add edi, 2 - dec ecx - mov word ptr [edi-2], ax - jnz cvtloop - } -} - - -void CASIODevice::Cvt16To16msb(void *pdst, void *psrc, UINT nSampleSize, UINT nSamples) -//------------------------------------------------------------------------------------- -{ - _asm { - mov ebx, psrc - mov edi, pdst - mov esi, nSampleSize - mov ecx, nSamples -cvtloop: - movsx eax, word ptr [ebx] - add ebx, esi - add edi, 2 - dec ecx - mov byte ptr [edi-2], ah - mov byte ptr [edi-1], al - jnz cvtloop - } -} - - -void CASIODevice::Cvt32To24(void *pdst, void *psrc, UINT nSampleSize, UINT nSamples) -//---------------------------------------------------------------------------------- -{ - _asm { - mov ebx, psrc - mov edi, pdst - mov esi, nSampleSize - mov ecx, nSamples -cvtloop: - mov eax, dword ptr [ebx] - add ebx, esi - add edi, 3 - mov edx, eax - shr eax, 8 - shr edx, 24 - dec ecx - mov byte ptr [edi-3], al - mov byte ptr [edi-2], ah - mov byte ptr [edi-1], dl - jnz cvtloop - } -} - - -void CASIODevice::Cvt32To24msb(void *pdst, void *psrc, UINT nSampleSize, UINT nSamples) -//------------------------------------------------------------------------------------- -{ - _asm { - mov ebx, psrc - mov edi, pdst - mov esi, nSampleSize - mov ecx, nSamples -cvtloop: - mov eax, dword ptr [ebx] - add ebx, esi - add edi, 3 - mov edx, eax - shr eax, 8 - shr edx, 24 - dec ecx - mov byte ptr [edi-3], dl - mov byte ptr [edi-2], ah - mov byte ptr [edi-1], al - jnz cvtloop - } -} - - -void CASIODevice::Cvt32To32(void *pdst, void *psrc, UINT nSampleSize, UINT nSamples, UINT nShift) -//----------------------------------------------------------------------------------------------- -{ - _asm { - mov ebx, psrc - mov edi, pdst - mov esi, nSampleSize - mov edx, nSamples - mov ecx, nShift -cvtloop: - mov eax, dword ptr [ebx] - add ebx, esi - add edi, 4 - sar eax, cl - dec edx - mov dword ptr [edi-4], eax - jnz cvtloop - } -} - - -void CASIODevice::Cvt32To32msb(void *pdst, void *psrc, UINT nSampleSize, UINT nSamples, UINT nShift) -//-------------------------------------------------------------------------------------------------- -{ - _asm { - mov ebx, psrc - mov edi, pdst - mov esi, nSampleSize - mov edx, nSamples - mov ecx, nShift -cvtloop: - mov eax, dword ptr [ebx] - add ebx, esi - add edi, 4 - sar eax, cl - bswap eax - dec edx - mov dword ptr [edi-4], eax - jnz cvtloop - } -} - - -const float _pow2_31 = 1.0f / 2147483648.0f; - -void CASIODevice::Cvt32To32f(void *pdst, void *psrc, UINT nSampleSize, UINT nSamples) -//----------------------------------------------------------------------------------- -{ - _asm { - mov ebx, psrc - mov edi, pdst - mov esi, nSampleSize - mov edx, nSamples - fld _pow2_31 -cvtloop: - fild dword ptr [ebx] - add ebx, esi - add edi, 4 - fmul st(0), st(1) - dec edx - fstp dword ptr [edi-4] - jnz cvtloop - fstp st(1) - } -} - - -void CASIODevice::Cvt32To64f(void *pdst, void *psrc, UINT nSampleSize, UINT nSamples) -//----------------------------------------------------------------------------------- -{ - _asm { - mov ebx, psrc - mov edi, pdst - mov esi, nSampleSize - mov edx, nSamples - fld _pow2_31 -cvtloop: - fild dword ptr [ebx] - add ebx, esi - add edi, 8 - fmul st(0), st(1) - dec edx - fstp qword ptr [edi-8] - jnz cvtloop - fstp st(1) - } -} - - -void CASIODevice::Cvt32To16(void *pdst, void *psrc, UINT nSampleSize, UINT nSamples) -//---------------------------------------------------------------------------------- -{ - _asm { - mov ebx, psrc - mov edi, pdst - mov esi, nSampleSize - mov ecx, nSamples -cvtloop: - mov eax, dword ptr [ebx] - add ebx, esi - add edi, 2 - sar eax, 16 - dec ecx - mov word ptr [edi-2], ax - jnz cvtloop - } -} - - -void CASIODevice::Cvt32To16msb(void *pdst, void *psrc, UINT nSampleSize, UINT nSamples) -//------------------------------------------------------------------------------------- -{ - _asm { - mov ebx, psrc - mov edi, pdst - mov esi, nSampleSize - mov ecx, nSamples -cvtloop: - mov eax, dword ptr [ebx] - add ebx, esi - add edi, 2 - bswap eax - dec ecx - mov word ptr [edi-2], ax - jnz cvtloop - } -} - BOOL CASIODevice::ReportASIOException(LPCSTR format,...) //------------------------------------------------------ { Modified: trunk/OpenMPT/sounddev/SoundDevice.h =================================================================== --- trunk/OpenMPT/sounddev/SoundDevice.h 2013-08-11 00:18:18 UTC (rev 2598) +++ trunk/OpenMPT/sounddev/SoundDevice.h 2013-08-11 17:33:10 UTC (rev 2599) @@ -160,7 +160,7 @@ void Start(); void Stop(); void Reset(); - virtual UINT HasFixedBitsPerSample() { return 0; } + virtual int HasFixedSampleFormat() { return 0; } virtual bool IsOpen() const = 0; virtual UINT GetNumBuffers() { return 0; } virtual float GetCurrentRealLatencyMS() { return GetRealLatencyMS(); } Modified: trunk/OpenMPT/sounddev/SoundDevices.h =================================================================== --- trunk/OpenMPT/sounddev/SoundDevices.h 2013-08-11 00:18:18 UTC (rev 2598) +++ trunk/OpenMPT/sounddev/SoundDevices.h 2013-08-11 17:33:10 UTC (rev 2599) @@ -202,7 +202,8 @@ enum { ASIO_BLOCK_LEN=1024 }; protected: IASIO *m_pAsioDrv; - UINT m_nChannels, m_nBitsPerSample, m_nAsioBufferLen, m_nAsioSampleSize; + UINT m_nChannels, m_nAsioBufferLen, m_nAsioSampleSize; + bool m_Float; BOOL m_bMixRunning; BOOL m_bPostOutput; UINT m_nCurrentDevice; @@ -211,7 +212,7 @@ ASIOCallbacks m_Callbacks; ASIOChannelInfo m_ChannelInfo[ASIO_MAX_CHANNELS]; ASIOBufferInfo m_BufferInfo[ASIO_MAX_CHANNELS]; - int m_FrameBuffer[ASIO_BLOCK_LEN]; + int32 m_FrameBuffer[ASIO_BLOCK_LEN]; private: void SetRenderSilence(bool silence, bool wait=false); @@ -232,7 +233,7 @@ void InternalStart(); void InternalStop(); bool IsOpen() const { return (m_pAsioDrv != NULL); } - UINT HasFixedBitsPerSample() { return m_nBitsPerSample; } + int HasFixedSampleFormat() { return m_Float ? 32+128 : 32; } UINT GetNumBuffers() { return 2; } float GetCurrentRealLatencyMS() { return m_nAsioBufferLen * 2 * 1000.0f / m_Settings.Samplerate; } @@ -255,18 +256,6 @@ static void SampleRateDidChange(ASIOSampleRate sRate); static long AsioMessage(long selector, long value, void* message, double* opt); static ASIOTime* BufferSwitchTimeInfo(ASIOTime* params, long doubleBufferIndex, ASIOBool directProcess); - static void EndianSwap64(void *pbuffer, UINT nSamples); - static void EndianSwap32(void *pbuffer, UINT nSamples); - static void Cvt16To16(void *pdst, void *psrc, UINT nSampleSize, UINT nSamples); - static void Cvt16To16msb(void *pdst, void *psrc, UINT nSampleSize, UINT nSamples); - static void Cvt32To16(void *pdst, void *psrc, UINT nSampleSize, UINT nSamples); - static void Cvt32To16msb(void *pdst, void *psrc, UINT nSampleSize, UINT nSamples); - static void Cvt32To24(void *pdst, void *psrc, UINT nSampleSize, UINT nSamples); - static void Cvt32To24msb(void *pdst, void *psrc, UINT nSampleSize, UINT nSamples); - static void Cvt32To32(void *pdst, void *psrc, UINT nSampleSize, UINT nSamples, UINT nShift); - static void Cvt32To32msb(void *pdst, void *psrc, UINT nSampleSize, UINT nSamples, UINT nShift); - static void Cvt32To32f(void *pdst, void *psrc, UINT nSampleSize, UINT nSamples); - static void Cvt32To64f(void *pdst, void *psrc, UINT nSampleSize, UINT nSamples); static BOOL ReportASIOException(LPCSTR format,...); }; Modified: trunk/OpenMPT/soundlib/SampleFormatConverters.h =================================================================== --- trunk/OpenMPT/soundlib/SampleFormatConverters.h 2013-08-11 00:18:18 UTC (rev 2598) +++ trunk/OpenMPT/soundlib/SampleFormatConverters.h 2013-08-11 17:33:10 UTC (rev 2599) @@ -10,6 +10,9 @@ #pragma once +#include "../soundlib/Endianness.h" + + // Byte offsets, from lowest significant to highest significant byte (for various functor template parameters) #define littleEndian32 0, 1, 2, 3 #define littleEndian24 0, 1, 2 @@ -239,6 +242,17 @@ }; template <> +struct Convert<int8, int24> +{ + typedef int24 input_t; + typedef int8 output_t; + forceinline output_t operator() (input_t val) + { + return int8(val >> 16); + } +}; + +template <> struct Convert<int8, int32> { typedef int32 input_t; @@ -276,6 +290,17 @@ }; template <> +struct Convert<int16, int24> +{ + typedef int24 input_t; + typedef int16 output_t; + forceinline output_t operator() (input_t val) + { + return int16(val >> 8); + } +}; + +template <> struct Convert<int16, int32> { typedef int32 input_t; @@ -301,6 +326,84 @@ } }; +template <> +struct Convert<int24, int8> +{ + typedef int8 input_t; + typedef int24 output_t; + forceinline output_t operator() (input_t val) + { + return int24(val << 8); + } +}; + +template <> +struct Convert<int24, int16> +{ + typedef int16 input_t; + typedef int24 output_t; + forceinline output_t operator() (input_t val) + { + return int24(val << 8); + } +}; + +template <> +struct Convert<int24, int32> +{ + typedef int32 input_t; + typedef int24 output_t; + forceinline output_t operator() (input_t val) + { + return int24(val >> 8); + } +}; + +template <> +struct Convert<float32, int32> +{ + typedef int32 input_t; + typedef float32 output_t; + forceinline output_t operator() (input_t val) + { + return val * (1.0f / static_cast<float>((unsigned int)1<<31)); + } +}; + +template <> +struct Convert<double, int32> +{ + typedef int32 input_t; + typedef double output_t; + forceinline output_t operator() (input_t val) + { + return val * (1.0 / static_cast<double>((unsigned int)1<<31)); + } +}; + +template <> +struct Convert<double, float> +{ + typedef float input_t; + typedef double output_t; + forceinline output_t operator() (input_t val) + { + return val; + } +}; + +template <> +struct Convert<float, double> +{ + typedef double input_t; + typedef float output_t; + forceinline output_t operator() (input_t val) + { + return static_cast<float>(val); + } +}; + + template <typename Tdst, typename Tsrc, int fractionalBits> struct ConvertFixedPoint; @@ -741,3 +844,19 @@ } } } + + +// Copy from an interleaed buffer of #channels. +template <typename SampleConversion> +void CopyInterleavedToChannel(typename SampleConversion::output_t *dst, const typename SampleConversion::input_t *src, std::size_t channels, std::size_t countChunk, std::size_t channel, SampleConversion conv = SampleConversion()) +//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +{ + SampleConversion sampleConv(conv); + src += channel; + for(std::size_t i = 0; i < countChunk; ++i) + { + *dst = sampleConv(*src); + src += channels; + dst++; + } +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |