问题
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>();
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.
- What is the right approach to make that?
- Is the processing that I call from the event is a static method/non-static?
回答1:
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.
EDIT: 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) { }
}
}
}
来源:https://stackoverflow.com/questions/31427289/parallel-operations-with-audio-stream-c-sharp