2016-06-02 29 views
0

現在再生中の曲からサンプルを取得し、その曲が再生されるときに波形を描画するには、NAudioを使用しています。私はAudioFileReaderToSampleProviderを使用して、すべてのサンプルをfloatとしてから、曲が再生されている間にInkCanvasにプロットします。私の問題は、サンプルがサウンドと一致しないように見えるということです。また、NAudioのソースコードにあるWPFの例でも、この同じ曲を使用して検証しています。この例では、波形はサウンドと一致しますが、アプリケーションでは波形が一致しません。だから私は、誰かが私がやっていること(または読んでいること)が間違っているかどうか、あるいは私の作図ロジックが間違っているかどうかを知る手伝いができるかどうか疑問に思いました私は、この描画アルゴリズムは非常に良いではありません知っているが、私は他を試してみましたが、彼らはまた、オーディオに従わないように見えるNAudioオーディオサンプルを取得

public partial class MainWindow : Window, INotifyPropertyChanged 
{ 
    private ISampleProvider provider; 
    private DispatcherTimer timer; 
    private AudioFileReader reader; 

    private WaveOut waveOut; 
    private StylusPointCollection topPoints, bottomPoints; 
    private DrawingAttributes attr; 

    private double canvasHeight, canvasWidth; 
    private int samplesGroupSize; 
    private double drawPos = 0; 

    private StrokeCollection _WaveformLines; 
    public StrokeCollection WaveformLines 
    { 
     get { return _WaveformLines; } 
     set 
     { 
      _WaveformLines = value; 
      OnPropertyChanged("WaveformLines"); 
     } 
    } 

    public MainWindow() 
    { 
     InitializeComponent(); 
     this.DataContext = this; 
    } 

    private void Window_Loaded(object sender, RoutedEventArgs e) 
    { 
     reader = new AudioFileReader("C:\\Users\\Agustin\\Desktop\\DragonRider.mp3"); 
     waveOut = new WaveOut(); 
     waveOut.Init(reader); 

     provider = reader.ToSampleProvider(); //Here I get the samples 
     reader.Position = 0; //Go to the position 0 after reading the samples 

     canvasHeight = Waveform.ActualHeight; 
     canvasWidth = Waveform.ActualWidth; 

     WaveformLines = new StrokeCollection(); 
     topPoints = new StylusPointCollection(); 
     topPoints.Add(new StylusPoint(0, (canvasHeight/2))); 
     topPoints.Changed += topPoints_Changed; 
     bottomPoints = new StylusPointCollection(); 
     bottomPoints.Add(new StylusPoint(0, (canvasHeight/2))); 
     bottomPoints.Changed += topPoints_Changed; 
     WaveformLines.Add(new Stroke(topPoints)); 
     WaveformLines.Add(new Stroke(bottomPoints)); 

     attr = new DrawingAttributes(); 
     attr.Color = Colors.Green; 
     attr.Width = 1.5; 
     attr.Height = 1; 

     timer = new DispatcherTimer(); 
     timer.Interval = TimeSpan.FromMilliseconds(1); 
     timer.Tick += timer_Tick; 
     timer.Start(); 
     samplesGroupSize = (int)(timer.Interval.TotalSeconds * reader.WaveFormat.SampleRate); //The value for this is 44. 
    } 

    private void PlayButton_Click(object sender, RoutedEventArgs e) 
    { 
     waveOut.Play(); 
    } 
    private void PauseButton_Click(object sender, RoutedEventArgs e) 
    { 
     waveOut.Pause(); 
    } 

    private void timer_Tick(object sender, EventArgs e) 
    { 
     if (waveOut.PlaybackState == PlaybackState.Playing) 
     { 
      TimeLabel.Content = string.Format("Time: {0}", reader.CurrentTime.ToString(@"mm\:ss\:ff")); //NEED TO KEEP WORKING 
      float[] samps = new float[samplesGroupSize]; 
      provider.Read(samps, 0, samps.Length); 
      float max = Max(samps); 
      float min = Min(samps); 
      topPoints.Add(new StylusPoint(drawPos, (canvasHeight/2) - ((canvasHeight/2) * max))); 
      bottomPoints.Add(new StylusPoint(drawPos, (canvasHeight/2) - ((canvasHeight/2) * min))); 
      drawPos += 2; 
      if (drawPos > canvasWidth) 
      { 
       WaveformLines.Clear(); 
       topPoints = new StylusPointCollection(); 
       topPoints.Add(new StylusPoint(0, (canvasHeight/2))); 
       bottomPoints = new StylusPointCollection(); 
       bottomPoints.Add(new StylusPoint(0, (canvasHeight/2))); 
       WaveformLines.Add(new Stroke(topPoints)); 
       WaveformLines.Add(new Stroke(bottomPoints)); 
       drawPos = 0; 
      } 
     } 
    } 

    private float Min(float[] samps) 
    { 
     float max = samps[0]; 
     foreach (float s in samps) 
     { 
      if (s > max) 
       max = s; 
     } 
     return max; 
    } 
    private float Max(float[] samps) 
    { 
     float min = samps[0]; 
     foreach (float s in samps) 
     { 
      if (s < min) 
       min = s; 
     } 
     return min; 
    } 

    //I excluded the INotifyPropertyChanged implementation, but in the 
    //actual code is located here 
} 

は、ここに私の現在のコードです。

ありがとうございました。

注:同様の質問があることを知っていますが、他の質問ではすでに使用しているAudioFileReaderまたはToSampleProviderなどを使用することをおすすめします。私のエラーはおそらく私がサンプルをどのように読んでいるか、おそらく私はいくつかのバイトが欠けているか、バイトをスキップしなければならないかもしれません。

+1

読み取り/再生**と最小/最大計算を処理する[WFPの例](https://github.com/naudio/NAudio/tree/master/NAudioWpfDemo/AudioPlaybackDemo)のコードの使用を真剣に検討する必要があります作業**。それはあなたに少しの努力を要しますが、私はそれがそれに値すると約束します。その後、正しいフォームであることがわかっているデータセットを使用して作業し、描画パートに集中できます。 'AudioPlayback.cs'と' SampleAggregator.cs'との関係をよく見てください。 –

+0

私はこのヒントを高く評価しています。もし私の唯一の選択肢であると思われるなら、おそらくソースコードのいくつかを使用することになりますが、私は実際にソースコードを使用しないようにしています。実際にソースコードを見ればプログラマーの自我を壊してしまいましたが、私はこの時間で暮らすことができます。 – Agustin0987

+0

この例を正しく使用すると、 'DispatchTimer'を使って波形描画の更新を駆り立てようとすることがなくなります。'SampleAggregator'からイベントデリゲートメソッド' OnMaximumCalculated'にコールバックを自動的に受け取るときに、100msecごとに1回(必要に応じてこの間隔を変更するプロパティを設定することができます)、これを行う方がずっと簡単だと思います。 –

答えて

0

読み取り/再生を処理するWFP exampleのコードの部分と、の最小/最大計算の部分を真剣に検討する必要があります。

少し努力するが、それはそれが価値があることを約束する。

正しい形式のデータセットを使用して作業し、描画部分に集中できます。詳しくはAudioPlayback.csとその関係をSampleAggregator.csとよく見てください。

また、サンプルが読み込まれて(再生されている)自動コールバックを取得すると、DispatchTimerを使用しようとするよりも、波形描画を更新する方がはるかに良い方法です。また、ウェーブバッファーを再読み込みすることもできます。可能であれば、それを避けたいと思っています。

EDIT:

Iは、コンバージョンコードをテストし、得られたfloat値(1から-1の範囲内で)正確であるように見えます。ですから、問題はWPFで波形をプロットする方法にあると思います。

関連する問題