2017-01-11 5 views
0

웨이브 파일을 열고 차트에서 진폭 및 주파수 응답을 플로팅하는 동안 다시 재생하고 싶습니다.nAudio로 재생하는 동안 .wav 파일을 플롯하는 중

바이트 배열이나 부동 소수점을 사용하는 함수가 있는데,이 함수는 나를 위해이 작업을 수행합니다.

내가하려고하는 것은 마지막으로 샘플링 한 오디오를 샘플링하여 그 시간을 함수에 나타내는 float 배열을 전달하는 것입니다.

ISampleProvider를 사용하여이 메서드를 읽으려고하는데 작동하지 않는 것 같습니다. 첫 번째 읽기는 완벽하게 작동하지만 후속 읽기에서 스레드가 충돌합니다 (간혹 첫 번째 읽기에서도 충돌이 발생 함).

이 내가 오디오를 설정하고있어 어떻게

이 파일이 잘 재생 :이 100ms의 타이머에서 실행되는

   _waveOut = new WaveOutEvent(); 
       _waveReader = new WaveFileReader(_cncFilePath.Substring(0, _cncFilePath.Length - 4) + "wav"); 
       _waveOutSampleProvider = new SampleChannel(_waveReader, true); 
       _waveOut.Init(_waveOutSampleProvider); 
       _waveOut.Play(); 

, 그것은 첫 번째 틱 완벽하게 작동, 두 번째는, 충돌합니다 잠금 장치가 켜져 있고 전체 프로그램이 충돌 할 때까지 다른 모든 호출이 백업됩니다. 스택 추적이 추가

private void WavOutChartTimeInterrupt(object waveReader) 
    { 
     lock (AudioLock) //todo add skipto code, use audio lock to do it. 
     { 
      try 
      { 
       var curPos = _waveOut.GetPositionTimeSpan(); //get currentPos 
       if (curPos <= AudioCurrentPosition) 
       { 
        AudioCurrentPosition = curPos; 
        return; 
       } 
       var bufferLength = (curPos - AudioCurrentPosition); 
       var samplesSec = _waveOutSampleProvider.WaveFormat.SampleRate; 
       var channels = _waveOut.OutputWaveFormat.Channels; 
       var length = (int) (bufferLength.TotalSeconds * samplesSec * channels) % (samplesSec * channels); 
       var wavOutBuffer = new float[length]; 
       _waveOutSampleProvider.Read(wavOutBuffer, 0, length); 

       AudioCurrentPosition = curPos; //update for vCNC with where we are 
      } 
      catch (Exception e) 
      { 
       string WTF = e.StackTrace; 

       throw new ArgumentException(@"Wave out buffer crashed" + e.StackTrace.ToString()); 
      } 
     } 

at NAudio.Wave.WaveFileReader.Read(Byte[] array, Int32 offset, Int32 count)\r\n  
at NAudio.Wave.SampleProviders.Pcm16BitToSampleProvider.Read(Single[] buffer, Int32 offset, Int32 count)\r\n  
at NAudio.Wave.SampleProviders.MeteringSampleProvider.Read(Single[] buffer, Int32 offset, Int32 count)\r\n 
at NAudio.Wave.SampleProviders.VolumeSampleProvider.Read(Single[] buffer, Int32 offset, Int32 sampleCount)\r\n 
at RecordCNC.Form1.WavOutChartTimeInterrupt(Object waveReader) in C:\\Cloud\\ITRI\\Visual Studio\\RecordCNC\\RecordCNC\\Form1.cs:line 715 

Haydan

+0

충돌로 인한 스택 추적/예외 데이터가 있습니까? – SynerCoder

+0

예외 유형을 볼 수있는 것보다 e.ToString()을 게시 할 수 있습니까? – SynerCoder

+0

아, 네가 내 문제를 해결할 수있게 해준 것 같아. 나는 읽은 길이가 블록 정렬의 배수인지 확인하지 못했다! (내가 생각했다지만 나는 아니었다) e.ToString()은 블록 정렬의 배수 여야 만했다 ... –

답변

0

문제는 내가 제대로 내가 요청 된 버퍼의 길이를 확인하지 않은 것이 었습니다 (내가 제대로 해냈다 바랍니다). 버퍼는 항상 블록 정렬의 배수 여야합니다.

private void WavOutChartTimeInterrupt(object waveReader) 
{ 
    lock (AudioLock) //todo add skipto code, use audio lock to do it. 
    { 
     try 
     { 
      var curPos = _waveOut.GetPositionTimeSpan(); //get currentPos 
      if (curPos <= AudioCurrentPosition) 
      { 
       AudioCurrentPosition = curPos; 
       return; 
      } 
      var bufferLength = (curPos - AudioCurrentPosition); 
      var samplesSec = _waveOutSampleProvider.WaveFormat.SampleRate; 
      var channels = _waveOut.OutputWaveFormat.Channels; 
      var length = (int) (bufferLength.TotalSeconds * samplesSec * channels) % (samplesSec * channels); 
      length -= length% (blockAlign/channels); //<- THIS FIXED IT 
      var wavOutBuffer = new float[length]; 
      _waveOutSampleProvider.Read(wavOutBuffer, 0, length); 

      AudioCurrentPosition = curPos; //update for vCNC with where we are 
     } 
     catch (Exception e) 
     { 
      string WTF = e.StackTrace; 

      throw new ArgumentException(@"Wave out buffer crashed" + e.StackTrace.ToString()); 
     } 
    }