From 0cb204d2bcbad0325486ceed2731bd1844d557c2 Mon Sep 17 00:00:00 2001 From: chudov Date: Sat, 22 Nov 2008 16:40:48 +0000 Subject: [PATCH] WAVWriter & LossyWAVSharp now support writing to stdout --- AudioCodecsDotNet/AudioCodecsDotNet.cs | 104 ++++++++++++++---------- CUEToolsLib/AudioReadWrite.cs | 2 +- LossyWAVSharp/LossyWAVSharp.csproj.user | 6 +- LossyWAVSharp/Program.cs | 17 +++- 4 files changed, 78 insertions(+), 51 deletions(-) diff --git a/AudioCodecsDotNet/AudioCodecsDotNet.cs b/AudioCodecsDotNet/AudioCodecsDotNet.cs index b9e335e..5af594a 100644 --- a/AudioCodecsDotNet/AudioCodecsDotNet.cs +++ b/AudioCodecsDotNet/AudioCodecsDotNet.cs @@ -505,15 +505,19 @@ namespace AudioCodecsDotNet public class WAVWriter : IAudioDest { - FileStream _IO; + Stream _IO; BinaryWriter _bw; int _bitsPerSample, _channelCount, _sampleRate, _blockAlign; long _sampleLen; string _path; private byte[] _sampleBuffer; - long hdrLen = 44; + long hdrLen = 0; + bool _headersWritten = false; + long _finalSampleCount; + List _chunks = null; + List _chunkFCCs = null; - public WAVWriter(string path, int bitsPerSample, int channelCount, int sampleRate) + public WAVWriter(string path, int bitsPerSample, int channelCount, int sampleRate, Stream IO) { _path = path; _bitsPerSample = bitsPerSample; @@ -521,10 +525,8 @@ namespace AudioCodecsDotNet _sampleRate = sampleRate; _blockAlign = _channelCount * ((_bitsPerSample + 7) / 8); - _IO = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read); + _IO = IO != null ? IO : new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read); _bw = new BinaryWriter(_IO); - - WriteHeaders(); } public bool SetTags(NameValueCollection tags) @@ -536,16 +538,14 @@ namespace AudioCodecsDotNet { if (_sampleLen > 0) throw new Exception("data already written, no chunks allowed"); - const uint fccData = 0x61746164; - _bw.Seek((int)hdrLen - 8, SeekOrigin.Begin); - _bw.Write(fcc); - _bw.Write((uint)data.Length); - _bw.Write(data); - if ((data.Length & 1) != 0) - _bw.Write((byte) 0); - _bw.Write(fccData); - _bw.Write((uint)0); - hdrLen += data.Length + (data.Length & 1) + 8; + if (_chunks == null) + { + _chunks = new List(); + _chunkFCCs = new List(); + } + _chunkFCCs.Add(fcc); + _chunks.Add(data); + hdrLen += 8 + data.Length + (data.Length & 1); } private void WriteHeaders() @@ -555,15 +555,20 @@ namespace AudioCodecsDotNet const uint fccFormat = 0x20746D66; const uint fccData = 0x61746164; - _bw.Write(fccRIFF); - _bw.Write((uint)0); - _bw.Write(fccWAVE); + bool wavex = _bitsPerSample != 16 && _bitsPerSample != 24; + hdrLen += 36 + (wavex ? 24 : 0) + 8; + + uint dataLen = (uint) (_finalSampleCount * _blockAlign); + uint dataLenPadded = dataLen + (dataLen & 1); + + _bw.Write(fccRIFF); + _bw.Write((uint)(dataLenPadded + hdrLen - 8)); + _bw.Write(fccWAVE); _bw.Write(fccFormat); - if (_bitsPerSample != 16 && _bitsPerSample != 24) + if (wavex) { _bw.Write((uint)40); - //_bw.Write((uint)16); _bw.Write((ushort)0xfffe); // WAVEX follows } else @@ -576,9 +581,7 @@ namespace AudioCodecsDotNet _bw.Write((uint)(_sampleRate * _blockAlign)); _bw.Write((ushort)_blockAlign); _bw.Write((ushort)((_bitsPerSample+7)/8*8)); - hdrLen = 36; - - if (_bitsPerSample != 16 && _bitsPerSample != 24) + if (wavex) { _bw.Write((ushort)22); // length of WAVEX structure _bw.Write((ushort)_bitsPerSample); @@ -595,40 +598,49 @@ namespace AudioCodecsDotNet _bw.Write((byte)0x38); _bw.Write((byte)0x9b); _bw.Write((byte)0x71); - - hdrLen += 24; } + if (_chunks != null) + for (int i = 0; i < _chunks.Count; i++) + { + _bw.Write(_chunkFCCs[i]); + _bw.Write((uint)_chunks[i].Length); + _bw.Write(_chunks[i]); + if ((_chunks[i].Length & 1) != 0) + _bw.Write((byte)0); + } _bw.Write(fccData); - _bw.Write((uint)0); - hdrLen += 8; + _bw.Write(dataLen); + + _headersWritten = true; } public void Close() { - const long maxFileSize = 0x7FFFFFFEL; - long dataLen, dataLenPadded; + if (_finalSampleCount == 0) + { + const long maxFileSize = 0x7FFFFFFEL; + long dataLen = _sampleLen * _blockAlign; + if ((dataLen & 1) == 1) + _bw.Write((byte)0); + if (dataLen + hdrLen > maxFileSize) + dataLen = ((maxFileSize - hdrLen) / _blockAlign) * _blockAlign; + long dataLenPadded = dataLen + (dataLen & 1); - dataLen = _sampleLen * _blockAlign; + _bw.Seek(4, SeekOrigin.Begin); + _bw.Write((uint)(dataLenPadded + hdrLen - 8)); - if ((dataLen & 1) == 1) - _bw.Write((byte)0); - - if (dataLen + hdrLen > maxFileSize) - dataLen = ((maxFileSize - hdrLen) / _blockAlign) * _blockAlign; - - dataLenPadded = dataLen + (dataLen & 1); - - _bw.Seek(4, SeekOrigin.Begin); - _bw.Write((uint)(dataLenPadded + hdrLen - 8)); - - _bw.Seek((int)hdrLen-4, SeekOrigin.Begin); - _bw.Write((uint)dataLen); + _bw.Seek((int)hdrLen - 4, SeekOrigin.Begin); + _bw.Write((uint)dataLen); + } _bw.Close(); _bw = null; _IO = null; + + if (_finalSampleCount != 0 && _sampleLen != _finalSampleCount) + throw new Exception("Samples written differs from the expected sample count."); } public void Delete() @@ -649,7 +661,7 @@ namespace AudioCodecsDotNet public long FinalSampleCount { - set { } + set { _finalSampleCount = value; } } public long BlockSize @@ -666,6 +678,8 @@ namespace AudioCodecsDotNet { if (sampleCount == 0) return; + if (!_headersWritten) + WriteHeaders(); if (_sampleBuffer == null || _sampleBuffer.Length < sampleCount * _blockAlign) _sampleBuffer = new byte[sampleCount * _blockAlign]; AudioSamples.FLACSamplesToBytes(buff, 0, _sampleBuffer, 0, diff --git a/CUEToolsLib/AudioReadWrite.cs b/CUEToolsLib/AudioReadWrite.cs index 2b2fb26..98f03d2 100644 --- a/CUEToolsLib/AudioReadWrite.cs +++ b/CUEToolsLib/AudioReadWrite.cs @@ -51,7 +51,7 @@ namespace CUEToolsLib { IAudioDest dest; switch (extension) { case ".wav": - dest = new WAVWriter(path, bitsPerSample, channelCount, sampleRate); + dest = new WAVWriter(path, bitsPerSample, channelCount, sampleRate, null); break; #if !MONO case ".flac": diff --git a/LossyWAVSharp/LossyWAVSharp.csproj.user b/LossyWAVSharp/LossyWAVSharp.csproj.user index f2c8722..b25529f 100644 --- a/LossyWAVSharp/LossyWAVSharp.csproj.user +++ b/LossyWAVSharp/LossyWAVSharp.csproj.user @@ -1,6 +1,10 @@  - - + "06 - Garden of Dreams - Mr. Hope Goes to Wall Street.wav" --stdout + C:\Work\cuetoolsnet\bin\x64\Release\ + + + "06 - Garden of Dreams - Mr. Hope Goes to Wall Street.wav" --stdout C:\Work\cuetoolsnet\bin\x64\Release\ \ No newline at end of file diff --git a/LossyWAVSharp/Program.cs b/LossyWAVSharp/Program.cs index c3bc6bc..8442fee 100644 --- a/LossyWAVSharp/Program.cs +++ b/LossyWAVSharp/Program.cs @@ -28,10 +28,12 @@ namespace LossyWAVSharp Console.WriteLine(); Console.WriteLine("Advanced Options:"); Console.WriteLine(); + Console.WriteLine("- if filename=\"-\" then WAV input is taken from STDIN."); Console.WriteLine("-q, --quality quality preset (10=highest quality, 0=lowest bitrate;"); Console.WriteLine(" default = --standard = 5; --insane = 10; --extreme = 7.5;"); Console.WriteLine(" --portable = 2.5)"); Console.WriteLine("-N --stdinname pseudo filename to use when input from STDIN."); + Console.WriteLine(" --stdout write processed WAV output to STDOUT."); } static void Main(string[] args) @@ -50,6 +52,7 @@ namespace LossyWAVSharp string stdinName = null; double quality = 5.0; bool createCorrection = false; + bool toStdout = false; for (int arg = 1; arg < args.Length; arg++) { bool ok = true; @@ -67,6 +70,8 @@ namespace LossyWAVSharp stdinName = args[arg]; else if ((args[arg] == "-q" || args[arg] == "--quality") && ++arg < args.Length) ok = double.TryParse(args[arg], out quality); + else if (args[arg] == "--stdout") + toStdout = true; else ok = false; if (!ok) @@ -75,20 +80,22 @@ namespace LossyWAVSharp return; } } - //Stream stdout = Console.OpenStandardOutput(); DateTime start = DateTime.Now; TimeSpan lastPrint = TimeSpan.FromMilliseconds(0); +#if !DEBUG try +#endif { WAVReader audioSource = new WAVReader(sourceFile, (sourceFile == "-" ? Console.OpenStandardInput() : null)); if (sourceFile == "-" && stdinName != null) sourceFile = stdinName; - WAVWriter audioDest = new WAVWriter(Path.ChangeExtension(sourceFile, ".lossy.wav"), audioSource.BitsPerSample, audioSource.ChannelCount, audioSource.SampleRate); - WAVWriter lwcdfDest = createCorrection ? new WAVWriter(Path.ChangeExtension(sourceFile, ".lwcdf.wav"), audioSource.BitsPerSample, audioSource.ChannelCount, audioSource.SampleRate) : null; + WAVWriter audioDest = new WAVWriter(Path.ChangeExtension(sourceFile, ".lossy.wav"), audioSource.BitsPerSample, audioSource.ChannelCount, audioSource.SampleRate, toStdout ? Console.OpenStandardOutput() : null); + WAVWriter lwcdfDest = createCorrection ? new WAVWriter(Path.ChangeExtension(sourceFile, ".lwcdf.wav"), audioSource.BitsPerSample, audioSource.ChannelCount, audioSource.SampleRate, null) : null; LossyWAVWriter lossyWAV = new LossyWAVWriter(audioDest, lwcdfDest, audioSource.BitsPerSample, audioSource.ChannelCount, audioSource.SampleRate, quality); int[,] buff = new int[0x1000, audioSource.ChannelCount]; Console.WriteLine("Filename : {0}", sourceFile); Console.WriteLine("File Info : {0}kHz; {1} channel; {2} bit; {3}", audioSource.SampleRate, audioSource.ChannelCount, audioSource.BitsPerSample, TimeSpan.FromSeconds(audioSource.Length * 1.0 / audioSource.SampleRate)); + lossyWAV.FinalSampleCount = (long) audioSource.Length; do { @@ -119,12 +126,14 @@ namespace LossyWAVSharp audioSource.Close(); lossyWAV.Close(); } +#if !DEBUG catch (Exception ex) { Console.WriteLine(); Console.WriteLine("Error: {0}", ex.Message); - Console.WriteLine("{0}", ex.StackTrace); + //Console.WriteLine("{0}", ex.StackTrace); } +#endif } } }