/// <summary> /// Manages threads taking files from the queue to process /// </summary> /// <param name="form"></param> public void ProcessSoundFiles(SoundVisualizer form) { Monitor.Enter(form.filesToProcess); //while condition check and .dequeue must be done 'atomically' - otherwise risk of race condition while (form.filesToProcess.Count != 0) { var fileToProcess = form.filesToProcess.Peek(); form.filesToProcess.Dequeue(); ProcessSoundFile(fileToProcess, fileToProcess.Substring(0, fileToProcess.Length - 4) + "_notes.ly", form); //cutting away .wav and adding notes.ly Monitor.Enter(form.filesToProcess); } Monitor.Exit(form.filesToProcess); }
/// <summary> /// Main method for processing the whole music sample /// </summary> /// <param name="inputFilePath"></param> /// <param name="outputFileName"></param> /// <param name="form"></param> public void ProcessSoundFile(string inputFilePath, string outputFileName, SoundVisualizer form) { if (form.filesToProcess != null) { Monitor.Exit(form.filesToProcess); } #region processing header BinaryReader headerStream = new BinaryReader(File.Open(inputFilePath, FileMode.Open)); ISoundReader soundReader = new WavSoundReader(); ProcessedMetaData metaData = soundReader.ReadHeader(headerStream); SampleSize = metaData.channelsCount * metaData.bitDepth / 8; sampleArraySize = (ChunkSize / SampleSize) + 1; headerStream.Close(); #endregion #region skipping header FileStream dataStream = new FileStream(inputFilePath, FileMode.Open, FileAccess.Read); dataStream.Seek(metaData.headerSize, SeekOrigin.Begin); #endregion #region processing data Complex[] complexSamples = new Complex[sampleArraySize]; Complex[] extendedComplexSamples = new Complex[2 * sampleArraySize - 2]; IWindowFunction window = new HannWindowFunction(); byte[] byteValues = soundReader.ReadDataBuffer(dataStream, ChunkSize + SampleSize); MusicSample musicSample = new MusicSample(metaData, inputFilePath); musicSample.Notes = new List <Note>(); while (dataStream.Position < dataStream.Length - ChunkSize) { complexSamples = ToComplexSamples(metaData.channelsCount == 1 ? byteValues : ExtractByteChannel(byteValues, isEven: true), metaData.bitDepth, metaData.channelsCount); INoiseDetector noiseDetector = new RMSNoiseDetector(2 << (metaData.bitDepth - 1)); if (noiseDetector.IsNoise(complexSamples)) { Note detectedNote = new Pause(); musicSample.Notes.Add(detectedNote); } else { extendedComplexSamples = ExtendSamples(complexSamples); window.Windowify(extendedComplexSamples); extendedComplexSamples = extendedComplexSamples.MakeFFT().MakeHPS(HPSIterationsCount); MaxFreqBin maxFreqBin = GetMaxFreqBin(extendedComplexSamples); double maxFreq = CalculateMaxFreq(maxFreqBin.BinNumber, metaData, sampleArraySize); NoteDetector noteDetector = new NoteDetector(); Note detectedNote = noteDetector.GetClosestNote(maxFreq / 2); musicSample.Notes.Add(detectedNote); } soundReader.MoveDataBuffer(dataStream, window.OverlapSize, byteValues); } IErrorCorrector corrector = new OverlapWindowCorrector(); corrector.Correct(musicSample); INoteLengthProcessor noteLengthProcessor = new DefaultNoteLengthProcessor(); noteLengthProcessor.ProcessSample(musicSample); StreamWriter writer2 = new StreamWriter(outputFileName); INoteWriter noteWriter = new LillyPondNoteWriter(); noteWriter.WriteAll(musicSample, writer2); #endregion }