音频流C#的并行操作 [英] parallel operations with audio stream c#

查看:100
本文介绍了音频流C#的并行操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用c#(wpf)录制声音,当声卡中的数据可用时,它将调用此事件:

I record sound in c#(wpf) and when data from sound card is available it calls this event:

void myWaveIn_DataAvailable(object sender, WaveInEventArgs e)
    {
        for (int index = 0; index < e.BytesRecorded; index += 2)//Here I convert in a loop the stream into floating number samples
        {

            short sample = (short)((e.Buffer[index + 1] << 8) |
                                    e.Buffer[index + 0]); 
            samples32Queue.Enqueue(sample/32768f);
        }
        //***Do some Processing with data inside Queue
    }

如您所见,我将每个样本从记录的缓冲区中推送到这样声明的队列中:

As you can see I push every sample from the recorded buffer to a queue that is declared like that:

Queue<float> samples32Queue = new Queue<float>();

您可以在for loop之后的事件内部看到,我想对Queue进行一些处理.我担心在处理数据时,声卡会产生新的样本,而我的处理会丢失.

As you can see inside the event after the for loop I want to do some processing on the Queue. I worry that while processing the data, a new samples will come from the sound card and my processing will got lost.

  1. 实现这一目标的正确方法是什么?
  2. 我从事件中调用的处理是静态方法还是非静态方法?

推荐答案

鉴于您可以缓冲样本并在以后进行处理,请考虑使用BlockingCollection. BlockingCollection是生产者-消费者模式的出色解决方案,据我了解,这就是您的情况.一方面,您具有myWaveIn_DataAvailable()方法,作为生产者,将样本添加到集合中;另一方面,您还有另一个消耗线程(尽管不必是另一个线程)来收集样本并进行处理.可以使用多种方式来实现使用者,并且在MSDN中已对它们进行了很好的记录.

Given the fact you can buffer the samples and process them later, consider using BlockingCollection. BlockingCollection is an excellent solution for producer-consumer pattern, which to my understanding, is your case. On one side you have myWaveIn_DataAvailable() method as a producer adding samples to the collection, and on the other end you have another consuming thread (it doesn't have to be another thread, though) collecting the samples and processing them. There are various ways the consumer can be implemented, and they are well documented in MSDN.

参见以下示例,我没有对其进行测试,但是它应该为您提供一个起点:

See the following example, I did not test it but it should give you a start point:

class ProducerConsumerExample
{
    BlockingCollection<float> samples32Collection;
    Thread consumer;
    public ProducerConsumerExample()
    {
        samples32Collection = new BlockingCollection<float>();
        consumer = new Thread(() => LaunchConsumer());
        consumer.Start();   //you don't have to luanch the consumer here...
    }
    void Terminate()    //Call this to terminate the consumer
    {
        consumer.Abort();
    }
    void myWaveIn_DataAvailable(object sender, WaveInEventArgs e)
    {
        for (int index = 0; index < e.BytesRecorded; index += 2)//Here I convert in a loop the stream into floating number samples
        {

            short sample = (short)((e.Buffer[index + 1] << 8) |
                                    e.Buffer[index + 0]);
            samples32Collection.Add(sample / 32768f);
        }
    }

    void LaunchConsumer()
    {
        while (true /* insert your abort condition here*/)
        {
            try
            {
                var sample = samples32Collection.Take();   //this thread will wait here until the producer add new item(s) to the collection
                Process(sample);    //in the meanwhile, more samples could be added to the collection 
                                    //but they will not be processed until this thread is done with Process(sample)
            }
            catch (InvalidOperationException) { }
        }
    }
}

这篇关于音频流C#的并行操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆