Optimized WMA decoder

This commit is contained in:
Grigory Chudov
2013-03-30 00:57:55 -04:00
parent db3f371d7d
commit 54e04a3413

View File

@@ -31,14 +31,14 @@ namespace CUETools.Codecs.WMA
public class WMAReader : IAudioSource public class WMAReader : IAudioSource
{ {
IWMSyncReader m_syncReader; IWMSyncReader m_syncReader;
INSSBuffer m_pSample;
int m_pSampleOffset = 0, m_pSampleSize = 0;
short m_wStreamNum = -1; short m_wStreamNum = -1;
int m_dwAudioOutputNum = -1; int m_dwAudioOutputNum = -1;
AudioPCMConfig pcm; AudioPCMConfig pcm;
byte[] samplesBuffer; long m_sampleCount = -1, m_sampleOffset = 0;
int _samplesInBuffer, _samplesBufferOffset;
long _sampleCount = -1, _sampleOffset = 0;
string _path; string _path;
//Stream _IO; //Stream _IO;
@@ -195,13 +195,8 @@ namespace CUETools.Codecs.WMA
pcm = new AudioPCMConfig(m_pWfx.wBitsPerSample, m_pWfx.nChannels, m_pWfx.nSamplesPerSec); pcm = new AudioPCMConfig(m_pWfx.wBitsPerSample, m_pWfx.nChannels, m_pWfx.nSamplesPerSec);
_path = path; _path = path;
int cbMax; //int cbMax;
m_syncReader.GetMaxOutputSampleSize(m_dwAudioOutputNum, out cbMax); //m_syncReader.GetMaxOutputSampleSize(m_dwAudioOutputNum, out cbMax);
//m_syncReader.GetMaxStreamSampleSize(m_wStreamNum, out cbMax);
//var ra = m_syncReader as IWMReaderAdvanced;
//ra.SetAllocateForOutput(m_dwAudioOutputNum, true);
samplesBuffer = new byte[cbMax];
} }
public void isValid(string filename) public void isValid(string filename)
@@ -220,15 +215,22 @@ namespace CUETools.Codecs.WMA
public void Close() public void Close()
{ {
//_IO.Close(); //_IO.Close();
if (m_pSample != null)
Marshal.ReleaseComObject(m_pSample);
if (m_syncReader != null)
{
m_syncReader.Close(); m_syncReader.Close();
Marshal.ReleaseComObject(m_syncReader); Marshal.ReleaseComObject(m_syncReader);
} }
m_pSample = null;
m_syncReader = null;
}
public long Length public long Length
{ {
get get
{ {
return _sampleCount; return m_sampleCount;
} }
} }
@@ -244,11 +246,11 @@ namespace CUETools.Codecs.WMA
{ {
get get
{ {
return _sampleOffset - _samplesInBuffer; return m_sampleOffset / PCM.BlockAlign;
} }
set set
{ {
if (_sampleCount < 0 || value > _sampleCount) if (m_sampleCount < 0 || value > m_sampleCount)
throw new Exception("seeking past end of stream"); throw new Exception("seeking past end of stream");
throw new NotSupportedException(); throw new NotSupportedException();
//if (value < Position || value > _sampleOffset) //if (value < Position || value > _sampleOffset)
@@ -311,67 +313,72 @@ namespace CUETools.Codecs.WMA
} }
} }
const int BS = 4;
public int Read(AudioBuffer buff, int maxLength) public int Read(AudioBuffer buff, int maxLength)
{ {
buff.Prepare(this, maxLength); buff.Prepare(this, maxLength);
int offset = 0; int buff_offset = 0;
int sampleCount = buff.Length; int buff_size = buff.ByteLength;
while (_samplesInBuffer < sampleCount) while (m_pSampleSize < buff_size)
{ {
if (_samplesInBuffer > 0) if (m_pSampleSize > 0)
{ {
Array.Copy(samplesBuffer, _samplesBufferOffset * BS, buff.Bytes, offset * BS, _samplesInBuffer * BS); IntPtr pdwBuffer;
sampleCount -= _samplesInBuffer; m_pSample.GetBuffer(out pdwBuffer);
offset += _samplesInBuffer; Marshal.Copy((IntPtr)(pdwBuffer.ToInt64() + m_pSampleOffset), buff.Bytes, buff_offset, m_pSampleSize);
_samplesInBuffer = 0; buff_size -= m_pSampleSize;
_samplesBufferOffset = 0; buff_offset += m_pSampleSize;
m_sampleOffset += m_pSampleSize;
m_pSampleSize = 0;
Marshal.ReleaseComObject(m_pSample);
m_pSample = null;
} }
INSSBuffer pSample;
long cnsSampleTime; long cnsSampleTime;
long cnsDuration; long cnsDuration;
SampleFlag flags; SampleFlag flags;
int dwOutputNum; int dwOutputNum;
short wStreamNum; short wStreamNum;
int dwLength;
IntPtr pdwBuffer;
try try
{ {
m_syncReader.GetNextSample(m_wStreamNum, out pSample, out cnsSampleTime, out cnsDuration, out flags, out dwOutputNum, out wStreamNum); m_syncReader.GetNextSample(m_wStreamNum, out m_pSample, out cnsSampleTime, out cnsDuration, out flags, out dwOutputNum, out wStreamNum);
} }
catch (COMException ex) catch (COMException ex)
{ {
// EOF // EOF
if (ex.ErrorCode == NSResults.E_NO_MORE_SAMPLES) if (ex.ErrorCode == NSResults.E_NO_MORE_SAMPLES)
{ {
_sampleCount = _sampleOffset; if ((m_sampleOffset % PCM.BlockAlign) != 0)
return offset; throw new Exception("(m_sampleOffset % PCM.BlockAlign) != 0");
m_sampleCount = m_sampleOffset / PCM.BlockAlign;
if ((buff_offset % PCM.BlockAlign) != 0)
throw new Exception("(buff_offset % PCM.BlockAlign) != 0");
return buff_offset / PCM.BlockAlign;
} }
throw ex; throw ex;
} }
//if (dwOutputNum != m_dwAudioOutputNum || wStreamNum != m_wStreamNum) //if (dwOutputNum != m_dwAudioOutputNum || wStreamNum != m_wStreamNum)
//{ //{
//} //}
pSample.GetBufferAndLength(out pdwBuffer, out dwLength); m_pSampleOffset = 0;
Marshal.Copy(pdwBuffer, samplesBuffer, 0, dwLength); m_pSample.GetLength(out m_pSampleSize);
Marshal.ReleaseComObject(pSample);
_samplesInBuffer = dwLength / BS;
_sampleOffset += _samplesInBuffer;
//_samplesInBuffer -= _samplesBufferOffset; // can be set by Seek, otherwise zero
//_sampleOffset += _samplesInBuffer;
} }
Array.Copy(samplesBuffer, _samplesBufferOffset * BS, buff.Bytes, offset * BS, sampleCount * BS); if (buff_size > 0)
_samplesInBuffer -= sampleCount; {
_samplesBufferOffset += sampleCount; IntPtr pdwBuffer;
if (_samplesInBuffer == 0) m_pSample.GetBuffer(out pdwBuffer);
_samplesBufferOffset = 0; Marshal.Copy((IntPtr)(pdwBuffer.ToInt64() + m_pSampleOffset), buff.Bytes, buff_offset, buff_size);
return offset + sampleCount; m_pSampleOffset += buff_size;
m_pSampleSize -= buff_size;
m_sampleOffset += buff_size;
buff_offset += buff_size;
buff_size = 0;
}
if ((buff_offset % PCM.BlockAlign) != 0)
throw new Exception("(buff_offset % PCM.BlockAlign) != 0");
return buff_offset / PCM.BlockAlign;
} }
} }
} }