将使用 .NetCore C# 在 Raspberry pi 上录制的音频保存到 Wav 文件 [英] Save to Wav file the audio recorded with .NetCore C# on Raspberry pi

查看:25
本文介绍了将使用 .NetCore C# 在 Raspberry pi 上录制的音频保存到 Wav 文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现很难找到一种方法将使用 OpenTk.NetStandard 捕获的音频存储到 NetCore C# 中的正确 .WAV 文件中.

I am finding very difficult to find a way to store the audio captured using OpenTk.NetStandard into a proper .WAV file in NetCore C#.

我正在寻找一种在 Raspberry pi 上运行时可以工作的解决方案,因此 NAudio 或任何特定于 Windows 的方法都无法解决我的问题.

What I am looking for is a solution which will work when running on a Raspberry pi, so NAudio or any Windows specific method won't solve my problem.

我发现了一些其他的 SO 答案,它们展示了如何使用 opentk 捕获音频,但没有关于如何将其存储在 wav 文件中.

I found a couple of other SO answers which show how to capture audio using opentk , but nothing about how to store it in a wav file.

这是应该从我从另一个 SO 问题中获取的麦克风读取数据的代码的摘录,我看到 AudioCapture 类是一个:

This is an extract of the code which should read data from the microphone I took from anther SO question, I see the AudioCapture class is the one to :

  const byte SampleToByte = 2;
  short[] _buffer = new short[512];
  int _sampling_rate = 16000;
  double _buffer_length_ms = 5000;
  var _recorders = AudioCapture.AvailableDevices;
  int buffer_length_samples = (int)((double)_buffer_length_ms  * _sampling_rate * 0.001 / BlittableValueType.StrideOf(_buffer));

  using (var audioCapture = new AudioCapture(_recorders.First(), _sampling_rate, ALFormat.Mono16, buffer_length_samples))
  {
      audioCapture.Start();
      int available_samples = audioCapture.AvailableSamples;        

      _buffer = new short[MathHelper.NextPowerOfTwo((int)(available_samples * SampleToByte / (double)BlittableValueType.StrideOf(_buffer) + 0.5))];

      if (available_samples > 0)
      {
          audioCapture.ReadSamples(_buffer, available_samples);

          int buf = AL.GenBuffer();
          AL.BufferData(buf, ALFormat.Mono16, buffer, (int)(available_samples * BlittableValueType.StrideOf(_buffer)), audio_capture.SampleFrequency);
          AL.SourceQueueBuffer(src, buf);

         // TODO: I assume this is where the save to WAV file logic should be placed...
      }

  }

任何帮助将不胜感激!

推荐答案

这是一个 .NET Core 控制台程序,它将使用 Mono 16 位数据编写 WAV 文件.您应该通读源代码中的链接以了解正在写入的值的情况.

Here is a .NET Core console program that will write a WAV file using Mono 16-bit data. There are links in the source code you should read through to understand what's going on with the values that are being written.

这将记录 10 秒的数据并将其保存为 WAV 格式的文件:

This will record 10 seconds of data and save it to a file in WAV format:

using OpenTK.Audio;
using OpenTK.Audio.OpenAL;
using System;
using System.IO;
using System.Threading;

class Program
{
    static void Main(string[] args)
    {
        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

        using (var f = File.OpenWrite(@"C:usersandydesktopout.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[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)
                    {
                        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);
        }
    }
}

这篇关于将使用 .NetCore C# 在 Raspberry pi 上录制的音频保存到 Wav 文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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