Xamarin.Android:文件写入受到另一种处理方式的影响

时间:2018-07-04 13:27:48

标签: c# xamarin.android fft file-writing scichart

我开发了 Xamarin Android应用,允许用户通过AudioRecord录制来自 micro 的声音,并将其写入.wav 文件中,并显示相关的频谱图。频谱图由SciChart库显示。

当我分别测试文件写作频谱图显示时,一切正常。

但是,如果我尝试同时使用它们,则会遇到一些问题:文件写得很好,但不是“正确”。 文件提供的声音似乎加速了,并且缺少一些音频缓冲区。

Activity上的按钮开始开始

((Button)FindViewById(Resource.Id.btnStart)).Click += async delegate
{
    isRecording = true;
    EnableButtons(true);
    audioService = new WavAudioService();
    audioService.samplesUpdated += AudioService_samplesUpdated;
    audioService.StartRecording();
};

AudioService中,此初始化 AudioRecord

public async Task StartRecording()
{
    audioRecord = new AudioRecord(AudioSource.Mic, 44100, ChannelIn.Mono, Android.Media.Encoding.Pcm16bit, buffer);                
    if (audioRecord.State == State.Initialized)
    {
        audioRecord.StartRecording();
    }
    isRecording = true;    
    recordingThread = new System.Threading.Thread(new ThreadStart(
        WriteAudioDataToFile
        ));
    recordingThread.Priority = System.Threading.ThreadPriority.Normal;
    recordingThread.Start(); 
}

写入时文件,而AudioRecord正在记录时:

private void WriteAudioDataToFile()
{
    byte[] data = new byte[bufferSize];
    string filename = GetTempFilename();
    FileOutputStream fos = null;
    try
    {
        fos = new FileOutputStream(filename);
    }
    catch (Java.IO.FileNotFoundException e)
    {
        // ...
    }
    int read = 0;
    if (null != fos)
    {
        while (isRecording)
        {
            read = audioRecord.Read(data, 0, bufferSize);           
            int[] bytesAsInts = Array.ConvertAll(data, c => (int)c);
            // call to FFT
            var res = FFT(bytesAsInts);
            if ((int)RecordStatus.ErrorInvalidOperation != read)
            {
                try
                {
                    fos.Write(data);
                }
                catch (Java.IO.IOException e)
                {
                    // ...
                }
            }
        }

        try
        {
            fos.Close();
        }
        catch (Java.IO.IOException e)
        {
            // ...
        }
    }
}

byte[]转换int[],供FFT() 计算使用:

public async Task<int[]> FFT(int[] y)
{
    var input = new AForge.Math.Complex[y.Length];
    for (int i = 0; i < y.Length; i++)
    {
        input[i] = new AForge.Math.Complex(y[i], 0);
    }
    FourierTransform.FFT(input, FourierTransform.Direction.Forward);
    var result = new int[y.Length / 2];
    // getting magnitude
    for (int i = 0; i < y.Length / 2 - 1; i++)
    {
        var current = Math.Sqrt(input[i].Re * input[i].Re + input[i].Im * input[i].Im);
        current = Math.Log10(current) * 10;
        result[i] = (int)current;
    }
    samplesUpdated(this, new SamplesUpdatedEventArgs(result));
    return result;
}

结果发送Activity上的委托方法:

private async void AudioService_samplesUpdated(object sender, System.EventArgs e)
{
    var audioService = (WavAudioService)sender;
    if (token.IsCancellationRequested)
    {
        audioService.StopRecording();
        return;
    }
    var arguments = e as SamplesUpdatedEventArgs;   
    if (arguments != null)
    {
        var samples = arguments.UpdatedSamples;
        if (samples.Length < (samplesCount / 2))
        {
            return;
        }
        UpdateHeatmapDataSeries(samples);       
    }
}

最后,UpdateHeatmapDataSeries()更新光谱图显示的

public async void UpdateHeatmapDataSeries(int[] data)
{
    var spectrogramSize = width * height;
    var fftSize = data.Length;
    var offset = spectrogramSize - fftSize;
    try
    {
        Array.Copy(Data, fftSize, Data, 0, offset);
        Array.Copy(data, 0, Data, offset, fftSize);
        heatmapSeries.UpdateZValues(Data);  
    }
    catch (System.Exception e)
    {
        // ...
    }
}

如果我通话从UpdateHeatmapDataSeries()移至AudioService_samplesUpdated(),我将不再遇到以下问题: 文件提供了“正确”的声音

我试图添加一些Threads来管理FFT()UpdateHeatmapDataSeries(),但是 这并没有改变 :< / p>

private void WriteAudioDataToFile()
{
    // ...
    while (isRecording)
    {
        read = audioRecord.Read(data, 0, bufferSize);           
        int[] bytesAsInts = Array.ConvertAll(data, c => (int)c);
        samplesUpdatedThread = new Thread(() => FFT(bytesAsInts));
        samplesUpdatedThread.Start();
        if ((int)RecordStatus.ErrorInvalidOperation != read)
        {
            try
            {
                fos.Write(data);
            }
            catch (Java.IO.IOException e)
            {
                // ...
            }
        }
    }
    // ...
}


private async void AudioService_samplesUpdated(object sender, System.EventArgs e)
{
    // ...
    var samples = arguments.UpdatedSamples;
    if (samples.Length < (samplesCount / 2))
    {
        return;
    }
    System.Threading.Thread thread = new System.Threading.Thread(() => UpdateHeatmapDataSeries(samples));
    thread.Start(); 
}

我忘记了什么吗?我该如何解决?

0 个答案:

没有答案