using NAudio.Wave; using SongVocalSectionAnalyser.Common.Logging; using System; using System.Collections.Generic; using System.IO; namespace SongVocalSectionAnalyser.AudioAnalysis { public class SongLoader { public static SongData LoadFromMp3File(string filePath, int msPerChunk, float chunkThreshold, int chunkDebounce, int chunksPerMa) { Logger.Trace("Try read mp3 file", filePath); using (var rdr = new Mp3FileReader(filePath)) { Logger.Trace("Mp3WaveFormat of file", rdr.Mp3WaveFormat); Logger.Trace("WaveFormat of file", rdr.WaveFormat); //using (var wavStream = WaveFormatConversionStream.CreatePcmStream(rdr)) return LoadFromWavStream(rdr, msPerChunk, chunkThreshold, chunkDebounce, chunksPerMa); } } public static SongData LoadFromWavFile(string filePath, int msPerChunk, float chunkThreshold, int chunkDebounce, int chunksPerMa) { using (var rdr = new WaveFileReader(filePath)) { using (var wavStream = WaveFormatConversionStream.CreatePcmStream(rdr)) return LoadFromWavStream(wavStream, msPerChunk, chunkThreshold, chunkDebounce, chunksPerMa); } } private static SongData LoadFromWavStream(WaveStream waveStream, int msPerChunk, float chunkThreshold, int chunkDebounce, int chunksPerMa) { var waveFormat = waveStream.WaveFormat; if (1 != waveFormat.Channels) throw new ArgumentException("Mono channel support only", nameof(waveStream)); if (16 != waveFormat.BitsPerSample) throw new ArgumentException("16 bit per sample support only", nameof(waveStream)); var sampleRate = waveFormat.SampleRate; var allSamples = ReadAllSamples(waveStream, waveFormat); return new SongData(allSamples, sampleRate, msPerChunk, chunkThreshold, chunkDebounce, chunksPerMa); } private static short[] ReadAllSamples(WaveStream waveStream, WaveFormat waveFormat) { short[] allSamples; { waveStream.Seek(0, SeekOrigin.Begin); var sampleData = new List((int)((waveStream.TotalTime.TotalSeconds + 1) * waveFormat.SampleRate)); var buffer = new byte[2]; while (true) { var read = waveStream.Read(buffer, 0, buffer.Length); if (buffer.Length != read) break; //little-endian var value = (short)(buffer[0] | (buffer[1] << 8)); sampleData.Add(value); } allSamples = sampleData.ToArray(); } return allSamples; } } }