Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
56 views
in Technique[技术] by (71.8m points)

c# - How to record from multiple devices at the same time using Opne TK?

I want to use Open TK to record on multiple devices at the same time.

As you can see in the question below, Save to Wav file the audio recorded with .NetCore C# on Raspberry pi I can record on one device, but if I try to do this on two devices at the same time and execute the following code, I may get the error "System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt."

What is the cause of this? Also, how can I write the code to do what I intended?

Task1 and task2 in the code below are almost the same, only the AudioCapture device(recorders[0], recorders[2]...) is different.

var recorders = AudioCapture.AvailableDevices;
for (int i = 0; i < recorders.Count; i++)
{
    Console.WriteLine(recorders[i]);
}
Console.WriteLine("-----");

const int samplingRate = 44100;     // Samples per second

const ALFormat alFormat = ALFormat.Mono16;
const ushort bitsPerSample = 16;    // Mono16 has 16 bits per sample
const ushort numChannels = 1;       // Mono16 has 1 channel

var task1 = Task.Run(() =>
{
    using (var f = File.OpenWrite("aaa.wav"))
    using (var sw = new BinaryWriter(f))
    {
        // Read This: http://soundfile.sapp.org/doc/WaveFormat/

        sw.Write(new char[] { 'R', 'I', 'F', 'F' });
        sw.Write(0); // will fill in later
        sw.Write(new char[] { 'W', 'A', 'V', 'E' });
        // "fmt " chunk (Google: WAVEFORMATEX structure)
        sw.Write(new char[] { 'f', 'm', 't', ' ' });
        sw.Write(16); // chunkSize (in bytes)
        sw.Write((ushort)1); // wFormatTag (PCM = 1)
        sw.Write(numChannels); // wChannels
        sw.Write(samplingRate); // dwSamplesPerSec
        sw.Write(samplingRate * numChannels * (bitsPerSample / 8)); // dwAvgBytesPerSec
        sw.Write((ushort)(numChannels * (bitsPerSample / 8))); // wBlockAlign
        sw.Write(bitsPerSample); // wBitsPerSample
                                    // "data" chunk
        sw.Write(new char[] { 'd', 'a', 't', 'a' });
        sw.Write(0); // will fill in later

        // 10 seconds of data. overblown, but it gets the job done
        const int bufferLength = samplingRate * 10;
        int samplesWrote = 0;

        Console.WriteLine($"Recording from: {recorders[2]}");

        using (var audioCapture = new AudioCapture(
            recorders[2], samplingRate, alFormat, bufferLength))
        {
            var buffer = new short[bufferLength];

            audioCapture.Start();
            for (int i = 0; i < 10; ++i)
            {
                Thread.Sleep(1000); // give it some time to collect samples

                var samplesAvailable = audioCapture.AvailableSamples;
                audioCapture.ReadSamples(buffer, samplesAvailable);
                for (var x = 0; x < samplesAvailable; ++x)
                {
                    sw.Write(buffer[x]);
                }

                samplesWrote += samplesAvailable;

                Console.WriteLine($"Wrote {samplesAvailable}/{samplesWrote} samples...");
            }
            audioCapture.Stop();
        }

        sw.Seek(4, SeekOrigin.Begin); // seek to overall size
        sw.Write(36 + samplesWrote * (bitsPerSample / 8) * numChannels);
        sw.Seek(40, SeekOrigin.Begin); // seek to data size position
        sw.Write(samplesWrote * (bitsPerSample / 8) * numChannels);
    }
});

Thread.Sleep(1000);

var task2 = Task.Run(() => {
    using (var g = File.OpenWrite("bbbb.wav"))
    using (var sx = new BinaryWriter(g))
    {
        // Read This: http://soundfile.sapp.org/doc/WaveFormat/

        sx.Write(new char[] { 'R', 'I', 'F', 'F' });
        sx.Write(0); // will fill in later
        sx.Write(new char[] { 'W', 'A', 'V', 'E' });
        // "fmt " chunk (Google: WAVEFORMATEX structure)
        sx.Write(new char[] { 'f', 'm', 't', ' ' });
        sx.Write(16); // chunkSize (in bytes)
        sx.Write((ushort)1); // wFormatTag (PCM = 1)
        sx.Write(numChannels); // wChannels
        sx.Write(samplingRate); // dwSamplesPerSec
        sx.Write(samplingRate * numChannels * (bitsPerSample / 8)); // dwAvgBytesPerSec
        sx.Write((ushort)(numChannels * (bitsPerSample / 8))); // wBlockAlign
        sx.Write(bitsPerSample); // wBitsPerSample
                                    // "data" chunk
        sx.Write(new char[] { 'd', 'a', 't', 'a' });
        sx.Write(0); // will fill in later

        // 10 seconds of data. overblown, but it gets the job done
        const int bufferLength = samplingRate * 10;
        int samplesWrote = 0;

        Console.WriteLine($"Recording from: {recorders[0]}");

        using (var audioCapture = new AudioCapture(
            recorders[0], samplingRate, alFormat, bufferLength))
        {
            var buffer = new short[bufferLength];

            audioCapture.Start();
            for (int i = 0; i < 10; ++i)
            {
                Thread.Sleep(1000); // give it some time to collect samples

                var samplesAvailable = audioCapture.AvailableSamples;
                audioCapture.ReadSamples(buffer, samplesAvailable);
                for (var x = 0; x < samplesAvailable; ++x)
                {
                    sx.Write(buffer[x]);
                }

                samplesWrote += samplesAvailable;

                Console.WriteLine($"Wrote {samplesAvailable}/{samplesWrote} samples...");
            }
            audioCapture.Stop();
        }

        sx.Seek(4, SeekOrigin.Begin); // seek to overall size
        sx.Write(36 + samplesWrote * (bitsPerSample / 8) * numChannels);
        sx.Seek(40, SeekOrigin.Begin); // seek to data size position
        sx.Write(samplesWrote * (bitsPerSample / 8) * numChannels);
    }
});

await Task.WhenAll(task1, task2);
question from:https://stackoverflow.com/questions/65938285/how-to-record-from-multiple-devices-at-the-same-time-using-opne-tk

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)
Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...