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>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="IStreamWrapper.cs" />
|
<Compile Include="IStreamWrapper.cs" />
|
||||||
|
<Compile Include="WaveFormatExtensible.cs" />
|
||||||
<Compile Include="WMAReader.cs" />
|
<Compile Include="WMAReader.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="Properties\Resources.Designer.cs">
|
<Compile Include="Properties\Resources.Designer.cs">
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ namespace CUETools.Codecs.WMA
|
|||||||
for (int dwIndex = 0; dwIndex < dwStreamCount; dwIndex++)
|
for (int dwIndex = 0; dwIndex < dwStreamCount; dwIndex++)
|
||||||
{
|
{
|
||||||
IWMStreamConfig pConfig = null;
|
IWMStreamConfig pConfig = null;
|
||||||
pProfile.GetStream(0, out pConfig);
|
pProfile.GetStream(dwIndex, out pConfig);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Guid guid;
|
Guid guid;
|
||||||
@@ -84,14 +84,15 @@ namespace CUETools.Codecs.WMA
|
|||||||
var pIWMMediaProps = pConfig as IWMMediaProps;
|
var pIWMMediaProps = pConfig as IWMMediaProps;
|
||||||
int cbType = 0;
|
int cbType = 0;
|
||||||
pIWMMediaProps.GetMediaType(null, ref cbType);
|
pIWMMediaProps.GetMediaType(null, ref cbType);
|
||||||
var mt = new AMMediaType();
|
var pMediaType = new AMMediaType();
|
||||||
mt.formatSize = cbType;
|
pMediaType.formatSize = cbType;
|
||||||
pIWMMediaProps.GetMediaType(mt, ref cbType);
|
pIWMMediaProps.GetMediaType(pMediaType, ref cbType);
|
||||||
if (mt.formatType != FormatType.WaveEx)
|
if (pMediaType.formatType != FormatType.WaveEx)
|
||||||
continue;
|
continue;
|
||||||
if (mt.subType != MediaSubType.WMAudio_Lossless)
|
if (pMediaType.subType != MediaSubType.WMAudio_Lossless)
|
||||||
continue;
|
continue;
|
||||||
m_wStreamNum = wStreamNum;
|
m_wStreamNum = wStreamNum;
|
||||||
|
pcm = WaveFormatExtensible.FromMediaType(pMediaType).GetConfig();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
@@ -110,7 +111,7 @@ namespace CUETools.Codecs.WMA
|
|||||||
m_syncReader.GetOutputNumberForStream(m_wStreamNum, out m_dwAudioOutputNum);
|
m_syncReader.GetOutputNumberForStream(m_wStreamNum, out m_dwAudioOutputNum);
|
||||||
IWMOutputMediaProps pProps;
|
IWMOutputMediaProps pProps;
|
||||||
m_syncReader.GetOutputProps(m_dwAudioOutputNum, out pProps);
|
m_syncReader.GetOutputProps(m_dwAudioOutputNum, out pProps);
|
||||||
var m_pWfx = new WaveFormatEx();
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
StringBuilder sName = null;
|
StringBuilder sName = null;
|
||||||
@@ -129,6 +130,12 @@ namespace CUETools.Codecs.WMA
|
|||||||
sName = new StringBuilder(iName);
|
sName = new StringBuilder(iName);
|
||||||
pProps.GetConnectionName(sName, ref 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 = new AMMediaType();
|
||||||
pMediaType.formatSize = cbType - Marshal.SizeOf(typeof(AMMediaType));
|
pMediaType.formatSize = cbType - Marshal.SizeOf(typeof(AMMediaType));
|
||||||
|
|
||||||
@@ -143,7 +150,15 @@ namespace CUETools.Codecs.WMA
|
|||||||
throw new Exception("not Audio");
|
throw new Exception("not Audio");
|
||||||
if (FormatType.WaveEx != pMediaType.formatType)
|
if (FormatType.WaveEx != pMediaType.formatType)
|
||||||
throw new Exception("not WaveEx");
|
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
|
finally
|
||||||
{
|
{
|
||||||
@@ -202,8 +217,6 @@ namespace CUETools.Codecs.WMA
|
|||||||
//{
|
//{
|
||||||
//}
|
//}
|
||||||
|
|
||||||
pcm = new AudioPCMConfig(m_pWfx.wBitsPerSample, m_pWfx.nChannels, m_pWfx.nSamplesPerSec);
|
|
||||||
|
|
||||||
//int cbMax;
|
//int cbMax;
|
||||||
//m_syncReader.GetMaxOutputSampleSize(m_dwAudioOutputNum, out 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)
|
if (pMediaType.majorType == MediaType.Audio && pMediaType.formatType == FormatType.WaveEx && pMediaType.subType == m_subType)
|
||||||
{
|
{
|
||||||
WaveFormatEx pWfx = new WaveFormatEx();
|
var pcm = WaveFormatExtensible.FromMediaType(pMediaType).GetConfig();
|
||||||
Marshal.PtrToStructure(pMediaType.formatPtr, pWfx);
|
if (PCM == null || (pcm.ChannelCount == PCM.ChannelCount && pcm.SampleRate == PCM.SampleRate && pcm.BitsPerSample >= PCM.BitsPerSample))
|
||||||
var info = new WMAFormatInfo()
|
yield return new WMAFormatInfo()
|
||||||
{
|
{
|
||||||
codec = iCodec,
|
codec = iCodec,
|
||||||
codecName = codecName.ToString(),
|
codecName = codecName.ToString(),
|
||||||
format = iFormat,
|
format = iFormat,
|
||||||
formatName = szDesc.ToString(),
|
formatName = szDesc.ToString(),
|
||||||
subType = pMediaType.subType,
|
subType = pMediaType.subType,
|
||||||
pcm = new AudioPCMConfig(pWfx.wBitsPerSample, pWfx.nChannels, pWfx.nSamplesPerSec)
|
pcm = pcm
|
||||||
};
|
};
|
||||||
if (PCM == null || (pWfx.nChannels == PCM.ChannelCount && pWfx.wBitsPerSample >= PCM.BitsPerSample && pWfx.nSamplesPerSec == PCM.SampleRate))
|
|
||||||
yield return info;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
@@ -268,27 +266,6 @@ namespace CUETools.Codecs.WMA
|
|||||||
private bool writingBegan = false;
|
private bool writingBegan = false;
|
||||||
private long sampleCount, finalSampleCount;
|
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
|
public long FinalSampleCount
|
||||||
{
|
{
|
||||||
set
|
set
|
||||||
@@ -335,27 +312,7 @@ namespace CUETools.Codecs.WMA
|
|||||||
pInput.GetMediaType(pMediaType, ref cbType);
|
pInput.GetMediaType(pMediaType, ref cbType);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var wfe = new WaveFormatExtensible();
|
var wfe = new WaveFormatExtensible(m_settings.PCM);
|
||||||
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;
|
|
||||||
}
|
|
||||||
Marshal.FreeCoTaskMem(pMediaType.formatPtr);
|
Marshal.FreeCoTaskMem(pMediaType.formatPtr);
|
||||||
pMediaType.formatPtr = IntPtr.Zero;
|
pMediaType.formatPtr = IntPtr.Zero;
|
||||||
pMediaType.formatSize = 0;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -24,6 +24,7 @@
|
|||||||
SPEAKER_TOP_BACK_CENTER = 0x10000,
|
SPEAKER_TOP_BACK_CENTER = 0x10000,
|
||||||
SPEAKER_TOP_BACK_RIGHT = 0x20000,
|
SPEAKER_TOP_BACK_RIGHT = 0x20000,
|
||||||
|
|
||||||
|
DIRECTOUT = 0,
|
||||||
KSAUDIO_SPEAKER_MONO = (SPEAKER_FRONT_CENTER),
|
KSAUDIO_SPEAKER_MONO = (SPEAKER_FRONT_CENTER),
|
||||||
KSAUDIO_SPEAKER_STEREO = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT),
|
KSAUDIO_SPEAKER_STEREO = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT),
|
||||||
KSAUDIO_SPEAKER_QUAD = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT),
|
KSAUDIO_SPEAKER_QUAD = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT),
|
||||||
@@ -45,9 +46,9 @@
|
|||||||
public int BlockAlign { get { return _channelCount * ((_bitsPerSample + 7) / 8); } }
|
public int BlockAlign { get { return _channelCount * ((_bitsPerSample + 7) / 8); } }
|
||||||
public SpeakerConfig ChannelMask { get { return _channelMask; } }
|
public SpeakerConfig ChannelMask { get { return _channelMask; } }
|
||||||
public bool IsRedBook { get { return _bitsPerSample == 16 && _channelCount == 2 && _sampleRate == 44100; } }
|
public bool IsRedBook { get { return _bitsPerSample == 16 && _channelCount == 2 && _sampleRate == 44100; } }
|
||||||
public SpeakerConfig GetDefaultChannelMask()
|
public static SpeakerConfig GetDefaultChannelMask(int channelCount)
|
||||||
{
|
{
|
||||||
switch (_channelCount)
|
switch (channelCount)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
return SpeakerConfig.KSAUDIO_SPEAKER_MONO;
|
return SpeakerConfig.KSAUDIO_SPEAKER_MONO;
|
||||||
@@ -68,15 +69,15 @@
|
|||||||
case 8:
|
case 8:
|
||||||
return SpeakerConfig.KSAUDIO_SPEAKER_7POINT1_SURROUND;
|
return SpeakerConfig.KSAUDIO_SPEAKER_7POINT1_SURROUND;
|
||||||
}
|
}
|
||||||
return (SpeakerConfig)((1 << _channelCount) - 1);
|
return (SpeakerConfig)((1 << channelCount) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AudioPCMConfig(int bitsPerSample, int channelCount, int sampleRate)
|
public AudioPCMConfig(int bitsPerSample, int channelCount, int sampleRate, SpeakerConfig channelMask = SpeakerConfig.DIRECTOUT)
|
||||||
{
|
{
|
||||||
_bitsPerSample = bitsPerSample;
|
_bitsPerSample = bitsPerSample;
|
||||||
_channelCount = channelCount;
|
_channelCount = channelCount;
|
||||||
_sampleRate = sampleRate;
|
_sampleRate = sampleRate;
|
||||||
_channelMask = GetDefaultChannelMask();
|
_channelMask = channelMask == 0 ? GetDefaultChannelMask(channelCount) : channelMask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -177,13 +177,14 @@ namespace CUETools.Codecs
|
|||||||
_br.ReadInt32(); // bytes per second
|
_br.ReadInt32(); // bytes per second
|
||||||
int _blockAlign = _br.ReadInt16();
|
int _blockAlign = _br.ReadInt16();
|
||||||
int _bitsPerSample = _br.ReadInt16();
|
int _bitsPerSample = _br.ReadInt16();
|
||||||
|
int _channelMask = 0;
|
||||||
pos += 16;
|
pos += 16;
|
||||||
|
|
||||||
if (fmtTag == 0xFFFEU && ckSize >= 34) // WAVE_FORMAT_EXTENSIBLE
|
if (fmtTag == 0xFFFEU && ckSize >= 34) // WAVE_FORMAT_EXTENSIBLE
|
||||||
{
|
{
|
||||||
_br.ReadInt16(); // CbSize
|
_br.ReadInt16(); // CbSize
|
||||||
_br.ReadInt16(); // ValidBitsPerSample
|
_br.ReadInt16(); // ValidBitsPerSample
|
||||||
int channelMask = _br.ReadInt32();
|
_channelMask = _br.ReadInt32();
|
||||||
fmtTag = _br.ReadUInt16();
|
fmtTag = _br.ReadUInt16();
|
||||||
pos += 10;
|
pos += 10;
|
||||||
}
|
}
|
||||||
@@ -191,7 +192,7 @@ namespace CUETools.Codecs
|
|||||||
if (fmtTag != 1) // WAVE_FORMAT_PCM
|
if (fmtTag != 1) // WAVE_FORMAT_PCM
|
||||||
throw new Exception("WAVE format tag not WAVE_FORMAT_PCM.");
|
throw new Exception("WAVE format tag not WAVE_FORMAT_PCM.");
|
||||||
|
|
||||||
pcm = new AudioPCMConfig(_bitsPerSample, _channelCount, _sampleRate);
|
pcm = new AudioPCMConfig(_bitsPerSample, _channelCount, _sampleRate, (AudioPCMConfig.SpeakerConfig)_channelMask);
|
||||||
if (pcm.BlockAlign != _blockAlign)
|
if (pcm.BlockAlign != _blockAlign)
|
||||||
throw new Exception("WAVE has strange BlockAlign");
|
throw new Exception("WAVE has strange BlockAlign");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ namespace CUETools.Codecs
|
|||||||
const uint fccFormat = 0x20746D66;
|
const uint fccFormat = 0x20746D66;
|
||||||
const uint fccData = 0x61746164;
|
const uint fccData = 0x61746164;
|
||||||
|
|
||||||
bool wavex = Settings.PCM.BitsPerSample != 16 && Settings.PCM.BitsPerSample != 24;
|
bool wavex = (Settings.PCM.BitsPerSample != 16 && Settings.PCM.BitsPerSample != 24) || Settings.PCM.ChannelMask != AudioPCMConfig.GetDefaultChannelMask(Settings.PCM.ChannelCount);
|
||||||
|
|
||||||
hdrLen += 36 + (wavex ? 24 : 0) + 8;
|
hdrLen += 36 + (wavex ? 24 : 0) + 8;
|
||||||
|
|
||||||
@@ -83,7 +83,10 @@ namespace CUETools.Codecs
|
|||||||
uint dataLenPadded = dataLen + (dataLen & 1);
|
uint dataLenPadded = dataLen + (dataLen & 1);
|
||||||
|
|
||||||
_bw.Write(fccRIFF);
|
_bw.Write(fccRIFF);
|
||||||
_bw.Write((uint)(dataLenPadded + hdrLen - 8));
|
if (_finalSampleCount <= 0)
|
||||||
|
_bw.Write((uint)0xffffffff);
|
||||||
|
else
|
||||||
|
_bw.Write((uint)(dataLenPadded + hdrLen - 8));
|
||||||
_bw.Write(fccWAVE);
|
_bw.Write(fccWAVE);
|
||||||
_bw.Write(fccFormat);
|
_bw.Write(fccFormat);
|
||||||
if (wavex)
|
if (wavex)
|
||||||
@@ -105,8 +108,8 @@ namespace CUETools.Codecs
|
|||||||
{
|
{
|
||||||
_bw.Write((ushort)22); // length of WAVEX structure
|
_bw.Write((ushort)22); // length of WAVEX structure
|
||||||
_bw.Write((ushort)Settings.PCM.BitsPerSample);
|
_bw.Write((ushort)Settings.PCM.BitsPerSample);
|
||||||
_bw.Write((uint)3); // speaker positions (3 == stereo)
|
_bw.Write((uint)Settings.PCM.ChannelMask);
|
||||||
_bw.Write((ushort)1); // PCM
|
_bw.Write((ushort)1); // PCM Guid
|
||||||
_bw.Write((ushort)0);
|
_bw.Write((ushort)0);
|
||||||
_bw.Write((ushort)0);
|
_bw.Write((ushort)0);
|
||||||
_bw.Write((ushort)0x10);
|
_bw.Write((ushort)0x10);
|
||||||
@@ -130,7 +133,10 @@ namespace CUETools.Codecs
|
|||||||
}
|
}
|
||||||
|
|
||||||
_bw.Write(fccData);
|
_bw.Write(fccData);
|
||||||
_bw.Write(dataLen);
|
if (_finalSampleCount <= 0)
|
||||||
|
_bw.Write((uint)0xffffffff);
|
||||||
|
else
|
||||||
|
_bw.Write(dataLen);
|
||||||
|
|
||||||
_headersWritten = true;
|
_headersWritten = true;
|
||||||
}
|
}
|
||||||
@@ -139,19 +145,19 @@ namespace CUETools.Codecs
|
|||||||
{
|
{
|
||||||
if (_finalSampleCount <= 0)
|
if (_finalSampleCount <= 0)
|
||||||
{
|
{
|
||||||
const long maxFileSize = 0x7FFFFFFEL;
|
|
||||||
long dataLen = _sampleLen * Settings.PCM.BlockAlign;
|
long dataLen = _sampleLen * Settings.PCM.BlockAlign;
|
||||||
if ((dataLen & 1) == 1)
|
|
||||||
_bw.Write((byte)0);
|
|
||||||
if (dataLen + hdrLen > maxFileSize)
|
|
||||||
dataLen = ((maxFileSize - hdrLen) / Settings.PCM.BlockAlign) * Settings.PCM.BlockAlign;
|
|
||||||
long dataLenPadded = dataLen + (dataLen & 1);
|
long dataLenPadded = dataLen + (dataLen & 1);
|
||||||
|
if (dataLenPadded + hdrLen - 8 < 0xffffffff)
|
||||||
|
{
|
||||||
|
if ((dataLen & 1) == 1)
|
||||||
|
_bw.Write((byte)0);
|
||||||
|
|
||||||
_bw.Seek(4, SeekOrigin.Begin);
|
_bw.Seek(4, SeekOrigin.Begin);
|
||||||
_bw.Write((uint)(dataLenPadded + hdrLen - 8));
|
_bw.Write((uint)(dataLenPadded + hdrLen - 8));
|
||||||
|
|
||||||
_bw.Seek((int)hdrLen - 4, SeekOrigin.Begin);
|
_bw.Seek((int)hdrLen - 4, SeekOrigin.Begin);
|
||||||
_bw.Write((uint)dataLen);
|
_bw.Write((uint)dataLen);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_bw.Close();
|
_bw.Close();
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ namespace LossyWAVSharp
|
|||||||
{
|
{
|
||||||
WAVReader audioSource = new WAVReader(sourceFile, (sourceFile == "-" ? Console.OpenStandardInput() : null));
|
WAVReader audioSource = new WAVReader(sourceFile, (sourceFile == "-" ? Console.OpenStandardInput() : null));
|
||||||
if (sourceFile == "-" && stdinName != null) sourceFile = stdinName;
|
if (sourceFile == "-" && stdinName != null) sourceFile = stdinName;
|
||||||
AudioPCMConfig pcm = outputBPS == 0 ? audioSource.PCM : new AudioPCMConfig(outputBPS, audioSource.PCM.ChannelCount, audioSource.PCM.SampleRate);
|
AudioPCMConfig pcm = outputBPS == 0 ? audioSource.PCM : new AudioPCMConfig(outputBPS, audioSource.PCM.ChannelCount, audioSource.PCM.SampleRate, audioSource.PCM.ChannelMask);
|
||||||
WAVWriter audioDest = new WAVWriter(Path.ChangeExtension(sourceFile, ".lossy.wav"), toStdout ? Console.OpenStandardOutput() : null, new WAVWriterSettings(pcm));
|
WAVWriter audioDest = new WAVWriter(Path.ChangeExtension(sourceFile, ".lossy.wav"), toStdout ? Console.OpenStandardOutput() : null, new WAVWriterSettings(pcm));
|
||||||
WAVWriter lwcdfDest = createCorrection ? new WAVWriter(Path.ChangeExtension(sourceFile, ".lwcdf.wav"), null, new WAVWriterSettings(audioSource.PCM)) : null;
|
WAVWriter lwcdfDest = createCorrection ? new WAVWriter(Path.ChangeExtension(sourceFile, ".lwcdf.wav"), null, new WAVWriterSettings(audioSource.PCM)) : null;
|
||||||
LossyWAVWriter lossyWAV = new LossyWAVWriter(audioDest, lwcdfDest, quality, new AudioEncoderSettings(audioSource.PCM));
|
LossyWAVWriter lossyWAV = new LossyWAVWriter(audioDest, lwcdfDest, quality, new AudioEncoderSettings(audioSource.PCM));
|
||||||
|
|||||||
@@ -473,6 +473,8 @@ return processor.Go();
|
|||||||
{
|
{
|
||||||
using (TextReader reader = new StringReader(settings))
|
using (TextReader reader = new StringReader(settings))
|
||||||
encoder.settings = encoder.settingsSerializer.Deserialize(reader) as AudioEncoderSettings;
|
encoder.settings = encoder.settingsSerializer.Deserialize(reader) as AudioEncoderSettings;
|
||||||
|
if (encoder.settings is UserDefinedEncoderSettings && (encoder.settings as UserDefinedEncoderSettings).Path == "")
|
||||||
|
encoders.Remove(encoder);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user