static void Main(string[] args) { if(args.Length<1){ Console.WriteLine("Usage: BPMAnalyzer <filename>.wav"); return; } var waveFile=new WaveFile(args[0]); const int frameSize=1024; var frameCount=(double)waveFile.FormatChunk.SamplesPerSecond/frameSize; var dataLength=waveFile.Data.Length; var sampleCount=dataLength/frameSize/2; var data=waveFile.Data.ToList(); var volume=(from index in Enumerable.Range(0,sampleCount) let sum=data.GetRange(frameSize*index,frameSize).Sum(d=>(double)d*d) select Math.Sqrt(sum/frameSize)).ToArray(); waveFile.Dispose(); var prev=0.0; var diff=(from v in volume let temp=prev select Math.Max((prev=v)-temp,0.0)).ToArray(); var indices=Enumerable.Range(0,diff.Length).AsParallel(); var r=(from i in Enumerable.Range(0,181) let freq=(i+60)/60.0 let theta=2.0*Math.PI*freq/frameCount let cosSum=indices.Sum(index=>HannWindow(index,diff.Length)*Math.Cos(theta*index)*diff[index])/sampleCount let sinSum=indices.Sum(index=>HannWindow(index,diff.Length)*Math.Sin(theta*index)*diff[index])/sampleCount select new{A=cosSum,B=sinSum,R=Math.Sqrt(cosSum*cosSum+sinSum*sinSum)}).ToArray(); var peaks=FindPeak(r.Select(obj=>obj.R).ToArray(),3); for(int i=0;i<peaks.Length;i++){ Console.WriteLine("[{0}]",i+1); int bpm=peaks[i]+60; Console.WriteLine("Peak BPM: {0}",bpm); var theta=Math.Atan2(r[peaks[i]].B,r[peaks[i]].A); if(theta<0) theta+=2.0*Math.PI; var peakFreq=(double)bpm/60; var startTime=theta/(2.0*Math.PI*peakFreq); var startBeat=theta/(2.0*Math.PI); Console.WriteLine("First beat time: {0} sec",startTime); Console.WriteLine("First beat: {0} beat",startBeat); } }