From 965761299715f11caf585000c252db48f3d0e3c1 Mon Sep 17 00:00:00 2001 From: Albrecht Lohofener Date: Tue, 9 Feb 2021 23:03:57 +0100 Subject: [PATCH 1/9] Initial Linux port using FFmpeg instead of NAudio. --- README.md | 41 ++++++++ TeddyBench/TeddyBench.csproj | 2 +- TonieAudio/TonieAudio.cs | 186 ++++++++++++++++++++++++++++++++--- TonieAudio/TonieAudio.csproj | 27 +++-- TonieAudio/packages.config | 5 + 5 files changed, 241 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index e29975a..5162fd7 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,44 @@ # Tonie file tool With this tool you can dump existing files of the famous audio box or create custom ones. + +# Linux +WARNING: The `TeddyBench` Linux port has alpha status. So don't use it unless you are a developer and you are able to understand cryptic error messages. It is not fully tested but converting files should work. + +It is tested with Ubuntu 20.04. + +## Requirements +Please install the following packages + +``` +# sudo apt install mono-complete xcb ffmpeg libgdiplus +``` + +## Running + +### General + +You have to run `TeddyBench` with `mono`. Using `wine` is not working. + +``` +# mono TeddyBench.exe +``` + +### Know issues +For some reasons TonieBench is running unstable with mono. So you can try the following steps. + +**A. Running with sudo (root)** + +``` +# sudo mono TeddyBench.exe +``` + +**B. Set some environment variables** + +``` +# export MONO_MANAGED_WATCHER=disabled +# export MONO_WINFORMS_XIM_STYLE=disabled +# mono TeddyBench.exe +``` +## Development +You can compile it directly under Linux with `monodevelop`. diff --git a/TeddyBench/TeddyBench.csproj b/TeddyBench/TeddyBench.csproj index e5807a1..937e291 100644 --- a/TeddyBench/TeddyBench.csproj +++ b/TeddyBench/TeddyBench.csproj @@ -1,5 +1,5 @@  - + diff --git a/TonieAudio/TonieAudio.cs b/TonieAudio/TonieAudio.cs index f565bf3..e183e08 100644 --- a/TonieAudio/TonieAudio.cs +++ b/TonieAudio/TonieAudio.cs @@ -41,6 +41,9 @@ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Xabe.FFmpeg; using static TonieFile.ProtoCoder; namespace TonieFile @@ -242,7 +245,11 @@ private void BuildFileList(string[] sources) { foreach (var source in sources) { - string item = source.Trim('"').Trim(Path.DirectorySeparatorChar); + string item; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + item = source; + else + item = source.Trim('"').Trim(Path.DirectorySeparatorChar); if (Directory.Exists(item)) { @@ -439,11 +446,82 @@ private void GenerateAudio(List sourceFiles, uint audioId, int bitRate, try { - var prefixStream = new Mp3FileReader(prefixFile); - var prefixResampled = new MediaFoundationResampler(prefixStream, outFormat); + Stream prefixResampled = new MemoryStream(); + + // Linux + string prefixTmpWavFile = ""; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + prefixTmpWavFile = Path.ChangeExtension(Path.GetTempFileName(), "wav"); + + //Console.Write(" Convert file " + sourceFile + " to WAV. Temp file " + prefixTmpWavFile); + + // The isReady flag and error test variables are not a nice solution but is working + bool isReadyPrefix = false; + String FFmpegErrorTextPrefix = ""; + + // Convert to WAV + Task.Run(async () => + { + try + { + // Convert to WAV and resample + IMediaInfo prefixInputFile = await FFmpeg.GetMediaInfo(sourceFile); + + IAudioStream prefixAudioStream = prefixInputFile.AudioStreams.First() + .SetCodec(AudioCodec.pcm_f32le) + .SetChannels(2) + .SetSampleRate(samplingRate); + + IConversionResult prefixConversionResult = await FFmpeg.Conversions.New() + .AddStream(prefixAudioStream) + .SetOutput(prefixTmpWavFile) + .Start(); + } + catch (Exception e) + { + FFmpegErrorTextPrefix = e.Message; + throw new Exception("FFmepg error " + e.Message + "\n"); + } + + isReadyPrefix = true; + }); + + while (!isReadyPrefix) + { + Thread.Sleep(200); + if (FFmpegErrorTextPrefix != "") + throw new Exception("FFmepg error: " + FFmpegErrorTextPrefix + "\n"); + } + + // Read WAV file + byte[] prefixWavBytes = File.ReadAllBytes(prefixTmpWavFile); + prefixResampled.Write(prefixWavBytes, 0, prefixWavBytes.Length); + prefixResampled.Seek(0, SeekOrigin.Begin); + + // Skip header, for some reason ffmpeg uses 46 bytes instead of 44 bytes + prefixResampled.Read(buffer, 0, 46); + } + else + { + var prefixStream = new Mp3FileReader(prefixFile); + var prefixResampledTmp = new MediaFoundationResampler(prefixStream, outFormat); + + // Convert NAudioStream to System.IO.Stream + byte[] sampleByte = { 0 }; + int read; + while ((read = prefixResampledTmp.Read(sampleByte, 0, sampleByte.Length)) > 0) + { + prefixResampled.Write(sampleByte, 0, read); + } + + prefixResampled.Seek(0, SeekOrigin.Begin); + } while (true) { + bytesReturned = prefixResampled.Read(buffer, 0, buffer.Length); if (bytesReturned <= 0) @@ -454,7 +532,11 @@ private void GenerateAudio(List sourceFiles, uint audioId, int bitRate, bool isEmpty = (buffer.Where(v => v != 0).Count() == 0); if (!isEmpty) { - float[] sampleBuffer = ConvertToFloat(buffer, bytesReturned, channels); + float[] sampleBuffer; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + sampleBuffer = MemoryMarshal.Cast(buffer.AsSpan()).ToArray(); + else + sampleBuffer = ConvertToFloat(buffer, bytesReturned, channels); if ((outputData.Length + 0x1000 + sampleBuffer.Length) >= maxSize) { @@ -464,6 +546,9 @@ private void GenerateAudio(List sourceFiles, uint audioId, int bitRate, } lastIndex = (uint)oggOut.PageCounter; } + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + File.Delete(prefixTmpWavFile); } catch (Exception ex) { @@ -471,9 +556,79 @@ private void GenerateAudio(List sourceFiles, uint audioId, int bitRate, } } + Stream streamResampled = new MemoryStream(); + + // Linux + string tmpWavFile = ""; + /* then the real audio file */ - var stream = new Mp3FileReader(sourceFile); - var streamResampled = new MediaFoundationResampler(stream, outFormat); + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + tmpWavFile = Path.ChangeExtension(Path.GetTempFileName(), "wav"); + + //Console.Write(" Convert file " + sourceFile + " to WAV. Temp file " + TmpWavFile); + + // The isReady flag and error test variables are not a nice solution but is working + bool isReady = false; + String FFmpegErrorText = ""; + + // Convert to WAV and resample + Task.Run(async () => + { + try + { + IMediaInfo inputFile = await FFmpeg.GetMediaInfo(sourceFile); + + IAudioStream audioStream = inputFile.AudioStreams.First() + .SetCodec(AudioCodec.pcm_f32le) + .SetChannels(2) + .SetSampleRate(samplingRate); + + IConversionResult conversionResult = await FFmpeg.Conversions.New() + .AddStream(audioStream) + .SetOutput(tmpWavFile) + .Start(); + } + catch (Exception e) + { + FFmpegErrorText = e.Message; + Console.WriteLine(e.Message); + throw new Exception("FFmepg error " + e.Message + "\n"); + } + + isReady = true; + }); + + while (!isReady) + { + Thread.Sleep(200); + if (FFmpegErrorText != "") + throw new Exception("FFmepg error: " + FFmpegErrorText + "\n"); + } + + // Read WAV file + byte[] wavBytes = File.ReadAllBytes(tmpWavFile); + streamResampled.Write(wavBytes, 0, wavBytes.Length); + streamResampled.Seek(0, SeekOrigin.Begin); + + // Skip header, for some reason ffmpeg uses 46 bytes instead of 44 bytes + streamResampled.Read(buffer, 0, 46); + } + else + { + var stream = new Mp3FileReader(sourceFile); + var streamResampledTmp = new MediaFoundationResampler(stream, outFormat); + + // Convert NAudioStream to System.IO.Stream + byte[] sampleByte = { 0 }; + int read; + while ((read = streamResampledTmp.Read(sampleByte, 0, sampleByte.Length)) > 0) + { + streamResampled.Write(sampleByte, 0, read); + } + + streamResampled.Seek(0, SeekOrigin.Begin); + } while (true) { @@ -485,7 +640,7 @@ private void GenerateAudio(List sourceFiles, uint audioId, int bitRate, } totalBytesRead += bytesReturned; - float progress = (float)stream.Position / stream.Length; + float progress = (float)streamResampled.Position / streamResampled.Length; if ((int)(progress * 20) != lastPct) { @@ -506,15 +661,22 @@ private void GenerateAudio(List sourceFiles, uint audioId, int bitRate, bool isEmpty = (buffer.Where(v => v != 0).Count() == 0); if (!isEmpty) { - float[] sampleBuffer = ConvertToFloat(buffer, bytesReturned, channels); - + float[] sampleBuffer; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + sampleBuffer = MemoryMarshal.Cast(buffer.AsSpan()).ToArray(); + else + sampleBuffer = ConvertToFloat(buffer, bytesReturned, channels); + oggOut.WriteSamples(sampleBuffer, 0, sampleBuffer.Length); } lastIndex = (uint)oggOut.PageCounter; } Console.WriteLine("]"); - stream.Close(); + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + File.Delete(tmpWavFile); + + streamResampled.Close(); } catch (OpusOggWriteStream.PaddingException e) { @@ -534,7 +696,7 @@ private void GenerateAudio(List sourceFiles, uint audioId, int bitRate, catch (Exception e) { Console.WriteLine(); - throw new Exception("Failed processing " + sourceFile); + throw new Exception("Failed processing " + sourceFile + "\n Error: " + e.Message + "\n"); } if (!warned && outputData.Length >= maxSize / 2) @@ -1008,4 +1170,4 @@ private OggPage GetOggPage(ref int offset) } } -} \ No newline at end of file +} diff --git a/TonieAudio/TonieAudio.csproj b/TonieAudio/TonieAudio.csproj index 8b82346..0ef4bd5 100644 --- a/TonieAudio/TonieAudio.csproj +++ b/TonieAudio/TonieAudio.csproj @@ -1,5 +1,5 @@  - + Debug @@ -9,7 +9,7 @@ Properties TonieAudio TonieAudio - v4.6 + v4.8 512 true @@ -18,7 +18,7 @@ true full false - bin\Debug\ + ..\TeddyBench\bin\Debug DEBUG;TRACE prompt 4 @@ -37,7 +37,6 @@ DEBUG;TRACE full x64 - 7.3 prompt MinimumRecommendedRules.ruleset @@ -47,7 +46,6 @@ true pdbonly x64 - 7.3 prompt MinimumRecommendedRules.ruleset @@ -57,7 +55,6 @@ false full x64 - 7.3 prompt MinimumRecommendedRules.ruleset true @@ -68,7 +65,6 @@ true pdbonly x64 - 7.3 prompt MinimumRecommendedRules.ruleset @@ -82,6 +78,23 @@ + + ..\packages\Xabe.FFmpeg.4.4.0\lib\netstandard2.0\Xabe.FFmpeg.dll + + + ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll + + + + ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll + + + + ..\packages\System.Runtime.CompilerServices.Unsafe.4.5.3\lib\net461\System.Runtime.CompilerServices.Unsafe.dll + + + ..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll + diff --git a/TonieAudio/packages.config b/TonieAudio/packages.config index e3f2a9a..4d0e143 100644 --- a/TonieAudio/packages.config +++ b/TonieAudio/packages.config @@ -3,4 +3,9 @@ + + + + + \ No newline at end of file From 14808f3cb6affe6d5729089d7a78993c91ec02b9 Mon Sep 17 00:00:00 2001 From: Albrecht Lohofener Date: Wed, 10 Feb 2021 15:43:21 +0100 Subject: [PATCH 2/9] Add support for non-MP3 files in Linux version --- TeddyBench/MainForm.cs | 15 +++++++++++---- TonieAudio/TonieAudio.cs | 10 ++++++++-- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/TeddyBench/MainForm.cs b/TeddyBench/MainForm.cs index 6702425..9576b8a 100644 --- a/TeddyBench/MainForm.cs +++ b/TeddyBench/MainForm.cs @@ -15,6 +15,7 @@ using System.Linq; using System.Net; using System.Net.Http; +using System.Runtime.InteropServices; using System.Text; using System.Text.RegularExpressions; using System.Threading; @@ -881,13 +882,19 @@ private void AddFiles(string[] fileNames) if (ask.ShowDialog() == DialogResult.OK) { + string[] extensions; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + extensions = new String[] {".mp3", ".ogg", ".wav", "wma", "aac"}; + else + extensions = new String[] {".mp3"}; + if (fileNames.Count() == 1) { string fileName = fileNames[0]; - if (fileName.ToLower().EndsWith(".mp3")) + if (extensions.Any(ext => fileName.ToLower().EndsWith(ext))) { - switch (MessageBox.Show("You are about to encode a single MP3, is this right?", "Encode a MP3 file", MessageBoxButtons.YesNo)) + switch (MessageBox.Show("You are about to encode an single audio file, is this right?", "Encode an audio file", MessageBoxButtons.YesNo)) { case DialogResult.No: return; @@ -916,9 +923,9 @@ private void AddFiles(string[] fileNames) } else { - if (fileNames.Where(f => !f.ToLower().EndsWith(".mp3")).Count() > 0) + if (fileNames.Where(f => !extensions.Any(ext => f.ToLower().EndsWith(ext))).Count() > 0) { - MessageBox.Show("Please select MP3 files only.", "Add file..."); + MessageBox.Show("Please select supported audio files only.", "Add file..."); return; } diff --git a/TonieAudio/TonieAudio.cs b/TonieAudio/TonieAudio.cs index e183e08..98336ae 100644 --- a/TonieAudio/TonieAudio.cs +++ b/TonieAudio/TonieAudio.cs @@ -288,9 +288,15 @@ private void BuildFileList(string[] sources) } else if (File.Exists(item)) { - if (!item.ToLower().EndsWith(".mp3")) + string[] extensions; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + extensions = new String[] { ".mp3", ".ogg", ".wav", "wma", "aac" }; + else + extensions = new String[] { ".mp3" }; + + if (!extensions.Any(ext => item.ToLower().EndsWith(ext))) { - throw new InvalidDataException("Specified item '" + item + "' is no MP3"); + throw new InvalidDataException("Specified item '" + item + "' is no a supported audio file"); } FileList.Add(item); } From e113fd1fa6d73040fb447a0f4fc73f4c96b74fcf Mon Sep 17 00:00:00 2001 From: Albrecht Lohofener Date: Sun, 14 Feb 2021 14:06:14 +0100 Subject: [PATCH 3/9] Switch to .net version 4.8 because of Linux compatibility --- Concentus.Oggfile/Concentus.Oggfile.csproj | 2 +- Concentus/Concentus.csproj | 2 +- Teddy/App.config | 2 +- Teddy/Teddy.csproj | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Concentus.Oggfile/Concentus.Oggfile.csproj b/Concentus.Oggfile/Concentus.Oggfile.csproj index f114cf0..a9cc75c 100644 --- a/Concentus.Oggfile/Concentus.Oggfile.csproj +++ b/Concentus.Oggfile/Concentus.Oggfile.csproj @@ -9,7 +9,7 @@ Properties Concentus.Oggfile Concentus.Oggfile - v4.6 + v4.8 512 true diff --git a/Concentus/Concentus.csproj b/Concentus/Concentus.csproj index b0dc74a..b196b31 100644 --- a/Concentus/Concentus.csproj +++ b/Concentus/Concentus.csproj @@ -9,7 +9,7 @@ Properties Concentus Concentus - v4.6 + v4.8 512 true diff --git a/Teddy/App.config b/Teddy/App.config index 2d2a12d..4bfa005 100644 --- a/Teddy/App.config +++ b/Teddy/App.config @@ -1,6 +1,6 @@ - + diff --git a/Teddy/Teddy.csproj b/Teddy/Teddy.csproj index 0b8cdee..34e0f08 100644 --- a/Teddy/Teddy.csproj +++ b/Teddy/Teddy.csproj @@ -10,7 +10,7 @@ Exe Teddy Teddy - v4.6 + v4.8 512 true true From 248f52d46803ecf1500be300aa739db7b0d54b19 Mon Sep 17 00:00:00 2001 From: Albrecht Lohofener Date: Sun, 14 Feb 2021 14:21:31 +0100 Subject: [PATCH 4/9] Add Linux start script --- Linux/TeddyBench | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100755 Linux/TeddyBench diff --git a/Linux/TeddyBench b/Linux/TeddyBench new file mode 100755 index 0000000..360440e --- /dev/null +++ b/Linux/TeddyBench @@ -0,0 +1,22 @@ +#!/bin/sh + +# check for mono +if ! type "mono" > /dev/null +then + echo "mono could not be found. Please read the README.md for installation instructions." + exit +fi + +# check for ffmpeg +if ! type "ffmpeg" > /dev/null +then + echo "ffmpeg could not be found. Please read the README.md for installation instructions." + exit +fi + +# Some exports to avoid crashes +export MONO_MANAGED_WATCHER=disabled +export MONO_WINFORMS_XIM_STYLE=disabled + +# Start TeddyBench +mono TeddyBench.exe From 7714306d828a51a53939bbc2590ab6d969e0cca9 Mon Sep 17 00:00:00 2001 From: Albrecht Lohofener Date: Mon, 15 Feb 2021 22:51:51 +0100 Subject: [PATCH 5/9] Add missing libs --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5162fd7..ac8f6bb 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ It is tested with Ubuntu 20.04. Please install the following packages ``` -# sudo apt install mono-complete xcb ffmpeg libgdiplus +# sudo apt install mono-complete xcb ffmpeg libgdiplus libcanberra-gtk-module libcanberra-gtk3-module ``` ## Running From 7c07f04c5f10851f602906a4de12c097d6e77a26 Mon Sep 17 00:00:00 2001 From: Albrecht Lohofener Date: Mon, 15 Feb 2021 22:52:29 +0100 Subject: [PATCH 6/9] Fix determining of correct of WAV header size --- TonieAudio/TonieAudio.cs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/TonieAudio/TonieAudio.cs b/TonieAudio/TonieAudio.cs index 98336ae..192e1d8 100644 --- a/TonieAudio/TonieAudio.cs +++ b/TonieAudio/TonieAudio.cs @@ -506,8 +506,12 @@ private void GenerateAudio(List sourceFiles, uint audioId, int bitRate, prefixResampled.Write(prefixWavBytes, 0, prefixWavBytes.Length); prefixResampled.Seek(0, SeekOrigin.Begin); - // Skip header, for some reason ffmpeg uses 46 bytes instead of 44 bytes - prefixResampled.Read(buffer, 0, 46); + // Skip WAV header + byte[] bytes = new byte[4]; + prefixResampled.Seek(16, 0); + prefixResampled.Read(bytes, 0, 4); + int Subchunk1Size = BitConverter.ToInt32(bytes, 0); // Get FMT size + prefixResampled.Read(buffer, 0, Subchunk1Size + 8); // Date starts at FMT size + 8 byte } else { @@ -617,8 +621,12 @@ private void GenerateAudio(List sourceFiles, uint audioId, int bitRate, streamResampled.Write(wavBytes, 0, wavBytes.Length); streamResampled.Seek(0, SeekOrigin.Begin); - // Skip header, for some reason ffmpeg uses 46 bytes instead of 44 bytes - streamResampled.Read(buffer, 0, 46); + // Skip WAV header + byte[] bytes = new byte[4]; + streamResampled.Seek(16, 0); + streamResampled.Read(bytes, 0, 4); + int Subchunk1Size = BitConverter.ToInt32(bytes, 0); // Get FMT size + streamResampled.Read(buffer, 0, Subchunk1Size + 8); // Date starts at FMT size + 8 byte } else { From b17051615801e6e962ea1f2baf44048b147b6e95 Mon Sep 17 00:00:00 2001 From: Albrecht Lohofener Date: Mon, 15 Feb 2021 22:53:04 +0100 Subject: [PATCH 7/9] Sort audio files in alphabetical order under Linux because of a scrappy Windows.Forms implementation --- TeddyBench/MainForm.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/TeddyBench/MainForm.cs b/TeddyBench/MainForm.cs index 9576b8a..23a0141 100644 --- a/TeddyBench/MainForm.cs +++ b/TeddyBench/MainForm.cs @@ -870,7 +870,14 @@ private void btnAdd_Click(object sender, EventArgs e) OpenFileDialog dlg = new OpenFileDialog(); dlg.Multiselect = true; - if (dlg.ShowDialog() == DialogResult.OK) + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + // Sort in alphabetical order because the Windows.Form dialog under Linux is scrappy + var list = dlg.FileNames.ToList(); + list.Sort(); + AddFiles(list.ToArray()); + } + else { AddFiles(dlg.FileNames); } From 0e1eae073e80d8558d10dc6a57177423bc24a971 Mon Sep 17 00:00:00 2001 From: Albrecht Lohofener Date: Tue, 16 Feb 2021 10:08:54 +0100 Subject: [PATCH 8/9] Fix regression --- TeddyBench/MainForm.cs | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/TeddyBench/MainForm.cs b/TeddyBench/MainForm.cs index 23a0141..a9df5c8 100644 --- a/TeddyBench/MainForm.cs +++ b/TeddyBench/MainForm.cs @@ -870,16 +870,19 @@ private void btnAdd_Click(object sender, EventArgs e) OpenFileDialog dlg = new OpenFileDialog(); dlg.Multiselect = true; - if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - { - // Sort in alphabetical order because the Windows.Form dialog under Linux is scrappy - var list = dlg.FileNames.ToList(); - list.Sort(); - AddFiles(list.ToArray()); - } - else + if (dlg.ShowDialog() == DialogResult.OK) { - AddFiles(dlg.FileNames); + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + // Sort in alphabetical order because the Windows.Form dialog under Linux is scrappy + var list = dlg.FileNames.ToList(); + list.Sort(); + AddFiles(list.ToArray()); + } + else + { + AddFiles(dlg.FileNames); + } } } From ba05b4707d5fba2a13846544355fb2248d7b1c36 Mon Sep 17 00:00:00 2001 From: Albrecht Lohofener Date: Tue, 16 Feb 2021 12:00:47 +0100 Subject: [PATCH 9/9] Fix again WAV header size calculation --- TonieAudio/TonieAudio.cs | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/TonieAudio/TonieAudio.cs b/TonieAudio/TonieAudio.cs index 192e1d8..4f3d071 100644 --- a/TonieAudio/TonieAudio.cs +++ b/TonieAudio/TonieAudio.cs @@ -511,7 +511,18 @@ private void GenerateAudio(List sourceFiles, uint audioId, int bitRate, prefixResampled.Seek(16, 0); prefixResampled.Read(bytes, 0, 4); int Subchunk1Size = BitConverter.ToInt32(bytes, 0); // Get FMT size - prefixResampled.Read(buffer, 0, Subchunk1Size + 8); // Date starts at FMT size + 8 byte + + // Skip some header information + prefixResampled.Read(buffer, 0, Subchunk1Size + 12); // Data starts at FMT size + 12 bytes + + // Read data chunk + prefixResampled.Read(bytes, 0, 4); + var str = System.Text.Encoding.Default.GetString(bytes); + if (str != "data") + throw new Exception("WAV error: Data section not found \n"); + + // Skip data length + prefixResampled.Read(bytes, 0, 4); } else { @@ -597,6 +608,7 @@ private void GenerateAudio(List sourceFiles, uint audioId, int bitRate, IConversionResult conversionResult = await FFmpeg.Conversions.New() .AddStream(audioStream) .SetOutput(tmpWavFile) + .AddParameter("-map_metadata -1 -fflags +bitexact -flags:v +bitexact -flags:a +bitexact") // Remove meta data .Start(); } catch (Exception e) @@ -626,7 +638,18 @@ private void GenerateAudio(List sourceFiles, uint audioId, int bitRate, streamResampled.Seek(16, 0); streamResampled.Read(bytes, 0, 4); int Subchunk1Size = BitConverter.ToInt32(bytes, 0); // Get FMT size - streamResampled.Read(buffer, 0, Subchunk1Size + 8); // Date starts at FMT size + 8 byte + + // Skip some header information + streamResampled.Read(buffer, 0, Subchunk1Size + 12); // Data starts at FMT size + 12 bytes + + // Read data chunk + streamResampled.Read(bytes, 0, 4); + var str = System.Text.Encoding.Default.GetString(bytes); + if(str != "data") + throw new Exception("WAV error: Data section not found \n"); + + // Skip data length + streamResampled.Read(bytes, 0, 4); } else {