mirror of
https://github.com/claunia/cuetools.net.git
synced 2025-12-16 18:14:25 +00:00
WMADecoder now supports multichannel audio
Better WAVE_FORMAT_EXTENSIBLE & channelMask support in WMA & WAV
This commit is contained in:
@@ -60,6 +60,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="IStreamWrapper.cs" />
|
||||
<Compile Include="WaveFormatExtensible.cs" />
|
||||
<Compile Include="WMAReader.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace CUETools.Codecs.WMA
|
||||
for (int dwIndex = 0; dwIndex < dwStreamCount; dwIndex++)
|
||||
{
|
||||
IWMStreamConfig pConfig = null;
|
||||
pProfile.GetStream(0, out pConfig);
|
||||
pProfile.GetStream(dwIndex, out pConfig);
|
||||
try
|
||||
{
|
||||
Guid guid;
|
||||
@@ -84,14 +84,15 @@ namespace CUETools.Codecs.WMA
|
||||
var pIWMMediaProps = pConfig as IWMMediaProps;
|
||||
int cbType = 0;
|
||||
pIWMMediaProps.GetMediaType(null, ref cbType);
|
||||
var mt = new AMMediaType();
|
||||
mt.formatSize = cbType;
|
||||
pIWMMediaProps.GetMediaType(mt, ref cbType);
|
||||
if (mt.formatType != FormatType.WaveEx)
|
||||
var pMediaType = new AMMediaType();
|
||||
pMediaType.formatSize = cbType;
|
||||
pIWMMediaProps.GetMediaType(pMediaType, ref cbType);
|
||||
if (pMediaType.formatType != FormatType.WaveEx)
|
||||
continue;
|
||||
if (mt.subType != MediaSubType.WMAudio_Lossless)
|
||||
if (pMediaType.subType != MediaSubType.WMAudio_Lossless)
|
||||
continue;
|
||||
m_wStreamNum = wStreamNum;
|
||||
pcm = WaveFormatExtensible.FromMediaType(pMediaType).GetConfig();
|
||||
break;
|
||||
}
|
||||
finally
|
||||
@@ -110,7 +111,7 @@ namespace CUETools.Codecs.WMA
|
||||
m_syncReader.GetOutputNumberForStream(m_wStreamNum, out m_dwAudioOutputNum);
|
||||
IWMOutputMediaProps pProps;
|
||||
m_syncReader.GetOutputProps(m_dwAudioOutputNum, out pProps);
|
||||
var m_pWfx = new WaveFormatEx();
|
||||
|
||||
try
|
||||
{
|
||||
StringBuilder sName = null;
|
||||
@@ -129,6 +130,12 @@ namespace CUETools.Codecs.WMA
|
||||
sName = new StringBuilder(iName);
|
||||
pProps.GetConnectionName(sName, ref iName);
|
||||
|
||||
if (pcm.ChannelCount > 2)
|
||||
{
|
||||
m_syncReader.SetOutputSetting(m_dwAudioOutputNum, Constants.g_wszEnableDiscreteOutput, AttrDataType.BOOL, new byte[] { 1, 0, 0, 0 }, 4);
|
||||
m_syncReader.SetOutputSetting(m_dwAudioOutputNum, Constants.g_wszSpeakerConfig, AttrDataType.DWORD, new byte[] { 0, 0, 0, 0 }, 4);
|
||||
}
|
||||
|
||||
pMediaType = new AMMediaType();
|
||||
pMediaType.formatSize = cbType - Marshal.SizeOf(typeof(AMMediaType));
|
||||
|
||||
@@ -143,7 +150,15 @@ namespace CUETools.Codecs.WMA
|
||||
throw new Exception("not Audio");
|
||||
if (FormatType.WaveEx != pMediaType.formatType)
|
||||
throw new Exception("not WaveEx");
|
||||
Marshal.PtrToStructure(pMediaType.formatPtr, m_pWfx);
|
||||
var wfe = new WaveFormatExtensible(pcm);
|
||||
Marshal.FreeCoTaskMem(pMediaType.formatPtr);
|
||||
pMediaType.formatPtr = IntPtr.Zero;
|
||||
pMediaType.formatSize = 0;
|
||||
pMediaType.formatPtr = Marshal.AllocCoTaskMem(Marshal.SizeOf(wfe));
|
||||
pMediaType.formatSize = Marshal.SizeOf(wfe);
|
||||
Marshal.StructureToPtr(wfe, pMediaType.formatPtr, false);
|
||||
pProps.SetMediaType(pMediaType);
|
||||
m_syncReader.SetOutputProps(m_dwAudioOutputNum, pProps);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -202,8 +217,6 @@ namespace CUETools.Codecs.WMA
|
||||
//{
|
||||
//}
|
||||
|
||||
pcm = new AudioPCMConfig(m_pWfx.wBitsPerSample, m_pWfx.nChannels, m_pWfx.nSamplesPerSec);
|
||||
|
||||
//int cbMax;
|
||||
//m_syncReader.GetMaxOutputSampleSize(m_dwAudioOutputNum, out cbMax);
|
||||
}
|
||||
|
||||
@@ -134,19 +134,17 @@ namespace CUETools.Codecs.WMA
|
||||
{
|
||||
if (pMediaType.majorType == MediaType.Audio && pMediaType.formatType == FormatType.WaveEx && pMediaType.subType == m_subType)
|
||||
{
|
||||
WaveFormatEx pWfx = new WaveFormatEx();
|
||||
Marshal.PtrToStructure(pMediaType.formatPtr, pWfx);
|
||||
var info = new WMAFormatInfo()
|
||||
{
|
||||
codec = iCodec,
|
||||
codecName = codecName.ToString(),
|
||||
format = iFormat,
|
||||
formatName = szDesc.ToString(),
|
||||
subType = pMediaType.subType,
|
||||
pcm = new AudioPCMConfig(pWfx.wBitsPerSample, pWfx.nChannels, pWfx.nSamplesPerSec)
|
||||
};
|
||||
if (PCM == null || (pWfx.nChannels == PCM.ChannelCount && pWfx.wBitsPerSample >= PCM.BitsPerSample && pWfx.nSamplesPerSec == PCM.SampleRate))
|
||||
yield return info;
|
||||
var pcm = WaveFormatExtensible.FromMediaType(pMediaType).GetConfig();
|
||||
if (PCM == null || (pcm.ChannelCount == PCM.ChannelCount && pcm.SampleRate == PCM.SampleRate && pcm.BitsPerSample >= PCM.BitsPerSample))
|
||||
yield return new WMAFormatInfo()
|
||||
{
|
||||
codec = iCodec,
|
||||
codecName = codecName.ToString(),
|
||||
format = iFormat,
|
||||
formatName = szDesc.ToString(),
|
||||
subType = pMediaType.subType,
|
||||
pcm = pcm
|
||||
};
|
||||
}
|
||||
}
|
||||
finally
|
||||
@@ -268,27 +266,6 @@ namespace CUETools.Codecs.WMA
|
||||
private bool writingBegan = false;
|
||||
private long sampleCount, finalSampleCount;
|
||||
|
||||
const ushort WAVE_FORMAT_EXTENSIBLE = 0xFFFE;
|
||||
const ushort WAVE_FORMAT_PCM = 1;
|
||||
|
||||
/// <summary>
|
||||
/// From WAVEFORMATEXTENSIBLE
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 2)]
|
||||
public struct WaveFormatExtensible
|
||||
{
|
||||
public short wFormatTag; /* format type */
|
||||
public short nChannels; /* number of channels (i.e. mono, stereo, etc.) */
|
||||
public int nSamplesPerSec; /* sample rate */
|
||||
public int nAvgBytesPerSec; /* for buffer estimation */
|
||||
public short nBlockAlign; /* block size of data */
|
||||
public short wBitsPerSample;
|
||||
public short cbSize;
|
||||
public short wValidBitsPerSample;
|
||||
public int dwChannelMask;
|
||||
public Guid SubFormat;
|
||||
}
|
||||
|
||||
public long FinalSampleCount
|
||||
{
|
||||
set
|
||||
@@ -335,27 +312,7 @@ namespace CUETools.Codecs.WMA
|
||||
pInput.GetMediaType(pMediaType, ref cbType);
|
||||
try
|
||||
{
|
||||
var wfe = new WaveFormatExtensible();
|
||||
wfe.nChannels = (short)m_settings.PCM.ChannelCount;
|
||||
wfe.nSamplesPerSec = m_settings.PCM.SampleRate;
|
||||
wfe.nBlockAlign = (short)m_settings.PCM.BlockAlign;
|
||||
wfe.wBitsPerSample = (short)m_settings.PCM.BitsPerSample;
|
||||
wfe.nAvgBytesPerSec = wfe.nSamplesPerSec * wfe.nBlockAlign;
|
||||
if ((m_settings.PCM.BitsPerSample == 8 || m_settings.PCM.BitsPerSample == 16 || m_settings.PCM.BitsPerSample == 24) &&
|
||||
(m_settings.PCM.ChannelCount == 1 || m_settings.PCM.ChannelCount == 2))
|
||||
{
|
||||
wfe.wFormatTag = unchecked((short)WAVE_FORMAT_PCM);
|
||||
wfe.cbSize = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
wfe.wFormatTag = unchecked((short)WAVE_FORMAT_EXTENSIBLE);
|
||||
wfe.cbSize = 22;
|
||||
wfe.wValidBitsPerSample = wfe.wBitsPerSample;
|
||||
wfe.nBlockAlign = (short)((wfe.wBitsPerSample / 8) * wfe.nChannels);
|
||||
wfe.dwChannelMask = (int)m_settings.PCM.ChannelMask;
|
||||
wfe.SubFormat = MediaSubType.PCM;
|
||||
}
|
||||
var wfe = new WaveFormatExtensible(m_settings.PCM);
|
||||
Marshal.FreeCoTaskMem(pMediaType.formatPtr);
|
||||
pMediaType.formatPtr = IntPtr.Zero;
|
||||
pMediaType.formatSize = 0;
|
||||
|
||||
91
CUETools.Codecs.WMA/WaveFormatExtensible.cs
Normal file
91
CUETools.Codecs.WMA/WaveFormatExtensible.cs
Normal file
@@ -0,0 +1,91 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
using WindowsMediaLib.Defs;
|
||||
|
||||
namespace CUETools.Codecs.WMA
|
||||
{
|
||||
/// <summary>
|
||||
/// From WAVEFORMATEXTENSIBLE
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 2)]
|
||||
public struct WaveFormatExtensible
|
||||
{
|
||||
public const ushort WAVE_FORMAT_EXTENSIBLE = 0xFFFE;
|
||||
public const ushort WAVE_FORMAT_PCM = 1;
|
||||
|
||||
public WaveFormatExtensible(AudioPCMConfig pcm)
|
||||
{
|
||||
this.nChannels = (short)pcm.ChannelCount;
|
||||
this.nSamplesPerSec = pcm.SampleRate;
|
||||
this.nBlockAlign = (short)pcm.BlockAlign;
|
||||
this.wBitsPerSample = (short)pcm.BitsPerSample;
|
||||
if ((pcm.BitsPerSample == 8 || pcm.BitsPerSample == 16 || pcm.BitsPerSample == 24) &&
|
||||
(pcm.ChannelCount == 1 || pcm.ChannelCount == 2))
|
||||
{
|
||||
this.wFormatTag = unchecked((short)WAVE_FORMAT_PCM);
|
||||
this.cbSize = 0;
|
||||
// just to make compiler happy
|
||||
this.wValidBitsPerSample = 0;
|
||||
this.dwChannelMask = 0;
|
||||
this.SubFormat = Guid.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.wFormatTag = unchecked((short)WAVE_FORMAT_EXTENSIBLE);
|
||||
this.cbSize = 22;
|
||||
this.wValidBitsPerSample = this.wBitsPerSample;
|
||||
this.nBlockAlign = (short)((this.wBitsPerSample / 8) * this.nChannels);
|
||||
this.dwChannelMask = (int)pcm.ChannelMask;
|
||||
this.SubFormat = MediaSubType.PCM;
|
||||
}
|
||||
this.nAvgBytesPerSec = this.nSamplesPerSec * this.nBlockAlign;
|
||||
}
|
||||
|
||||
public static WaveFormatExtensible FromMediaType(AMMediaType pMediaType)
|
||||
{
|
||||
if (MediaType.Audio != pMediaType.majorType)
|
||||
throw new Exception("not Audio");
|
||||
if (FormatType.WaveEx != pMediaType.formatType || pMediaType.formatSize < 18)
|
||||
throw new Exception("not WaveEx");
|
||||
WaveFormatEx pWfx = new WaveFormatEx();
|
||||
Marshal.PtrToStructure(pMediaType.formatPtr, pWfx);
|
||||
if (pWfx.wFormatTag == unchecked((short)WAVE_FORMAT_EXTENSIBLE) && pWfx.cbSize >= 22)
|
||||
{
|
||||
var pWfe = new WaveFormatExtensible();
|
||||
Marshal.PtrToStructure(pMediaType.formatPtr, pWfe);
|
||||
return pWfe;
|
||||
}
|
||||
return new WaveFormatExtensible() {
|
||||
nChannels = pWfx.nChannels,
|
||||
nSamplesPerSec = pWfx.nSamplesPerSec,
|
||||
nBlockAlign = pWfx.nBlockAlign,
|
||||
wBitsPerSample = pWfx.wBitsPerSample,
|
||||
nAvgBytesPerSec = pWfx.nAvgBytesPerSec,
|
||||
wFormatTag = pWfx.wFormatTag,
|
||||
cbSize = 0
|
||||
};
|
||||
}
|
||||
|
||||
public AudioPCMConfig GetConfig()
|
||||
{
|
||||
return new AudioPCMConfig(
|
||||
wBitsPerSample,
|
||||
nChannels,
|
||||
nSamplesPerSec,
|
||||
(AudioPCMConfig.SpeakerConfig)(wFormatTag == unchecked((short)WAVE_FORMAT_EXTENSIBLE) && cbSize >= 22 ? dwChannelMask : 0));
|
||||
}
|
||||
|
||||
public short wFormatTag; /* format type */
|
||||
public short nChannels; /* number of channels (i.e. mono, stereo, etc.) */
|
||||
public int nSamplesPerSec; /* sample rate */
|
||||
public int nAvgBytesPerSec; /* for buffer estimation */
|
||||
public short nBlockAlign; /* block size of data */
|
||||
public short wBitsPerSample;
|
||||
public short cbSize;
|
||||
public short wValidBitsPerSample;
|
||||
public int dwChannelMask;
|
||||
public Guid SubFormat;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user