SongLoader.cs 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. using NAudio.Wave;
  2. using SongVocalSectionAnalyser.Common.Logging;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.IO;
  6. namespace SongVocalSectionAnalyser.AudioAnalysis
  7. {
  8. public class SongLoader
  9. {
  10. public static SongData LoadFromMp3File(string filePath, int msPerChunk, float chunkThreshold, int chunkDebounce, int chunksPerMa)
  11. {
  12. Logger.Trace("Try read mp3 file", filePath);
  13. using (var rdr = new Mp3FileReader(filePath))
  14. {
  15. Logger.Trace("Mp3WaveFormat of file", rdr.Mp3WaveFormat);
  16. Logger.Trace("WaveFormat of file", rdr.WaveFormat);
  17. //using (var wavStream = WaveFormatConversionStream.CreatePcmStream(rdr))
  18. return LoadFromWavStream(rdr, msPerChunk, chunkThreshold, chunkDebounce, chunksPerMa);
  19. }
  20. }
  21. public static SongData LoadFromWavFile(string filePath, int msPerChunk, float chunkThreshold, int chunkDebounce, int chunksPerMa)
  22. {
  23. using (var rdr = new WaveFileReader(filePath))
  24. {
  25. using (var wavStream = WaveFormatConversionStream.CreatePcmStream(rdr))
  26. return LoadFromWavStream(wavStream, msPerChunk, chunkThreshold, chunkDebounce, chunksPerMa);
  27. }
  28. }
  29. private static SongData LoadFromWavStream(WaveStream waveStream, int msPerChunk, float chunkThreshold, int chunkDebounce, int chunksPerMa)
  30. {
  31. var waveFormat = waveStream.WaveFormat;
  32. if (1 != waveFormat.Channels) throw new ArgumentException("Mono channel support only", nameof(waveStream));
  33. if (16 != waveFormat.BitsPerSample) throw new ArgumentException("16 bit per sample support only", nameof(waveStream));
  34. var sampleRate = waveFormat.SampleRate;
  35. var allSamples = ReadAllSamples(waveStream, waveFormat);
  36. return new SongData(allSamples, sampleRate, msPerChunk, chunkThreshold, chunkDebounce, chunksPerMa);
  37. }
  38. private static short[] ReadAllSamples(WaveStream waveStream, WaveFormat waveFormat)
  39. {
  40. short[] allSamples;
  41. {
  42. waveStream.Seek(0, SeekOrigin.Begin);
  43. var sampleData =
  44. new List<short>((int)((waveStream.TotalTime.TotalSeconds + 1) * waveFormat.SampleRate));
  45. var buffer = new byte[2];
  46. while (true)
  47. {
  48. var read = waveStream.Read(buffer, 0, buffer.Length);
  49. if (buffer.Length != read) break;
  50. //little-endian
  51. var value = (short)(buffer[0] | (buffer[1] << 8));
  52. sampleData.Add(value);
  53. }
  54. allSamples = sampleData.ToArray();
  55. }
  56. return allSamples;
  57. }
  58. }
  59. }