Воспроизведение звука в .NET с использованием сгенерированных данных формы сигнала

StackOverflow https://stackoverflow.com/questions/1084433

Вопрос

Как я могу воспроизвести звук на основе данных формы волны, которые моя .NET-программа генерирует на основе пользовательского ввода и математических функций?

Под "данными о форме волны" я подразумеваю значения SPL (уровня звукового давления) во временном ряду с фиксированным интервалом (вероятно, 44,1 кГц).Я предполагаю, что для этого требуется какое-то устройство потокового буфера.

Обратите внимание, что это должно происходить в режиме реального времени, поэтому простого создания файла .wav и последующего воспроизведения этого будет недостаточно.VB.NET предпочтителен, но C # также приемлем.

Просто чтобы прояснить:То, что я ищу, - это простой пример рабочего кода.

Это было полезно?

Решение

Вы можете сделать это с помощью НАудио.Вы создаете поток, производный от WaveStream, и в его переопределенном методе чтения возвращаете свои выборки, которые вы можете сгенерировать на лету.У вас есть контроль над размером буферов, используемых звуковой картой, что дает вам контроль над задержкой.

Другие советы

Как играть из массива дублей

    PlayerEx pl = new PlayerEx();

    private static void PlayArray(PlayerEx pl)
    {
        double fs = 8000; // sample freq
        double freq = 1000; // desired tone
        short[] mySound = new short[4000];
        for (int i = 0; i < 4000; i++)
        {
            double t = (double)i / fs; // current time
            mySound[i] = (short)(Math.Cos(t * freq) * (short.MaxValue));
        }
        IntPtr format = AudioCompressionManager.GetPcmFormat(1, 16, (int)fs);
        pl.OpenPlayer(format);
        byte[] mySoundByte = new byte[mySound.Length * 2];
        Buffer.BlockCopy(mySound, 0, mySoundByte, 0, mySoundByte.Length);
        pl.AddData(mySoundByte);
        pl.StartPlay();
    }

Проверьте этот поток при загрузке Направленный звук буфер с произвольными данными и их воспроизведение.

За комментарий:Да, я знаю.Вам нужно будет перевести C ++ на C # или VB.NET .Но концепция - это то, что важно.Вы создаете вторичный буфер DirectSound, а затем используете его для потоковой передачи в ваш основной буфер и воспроизведения.

ИррКланг, BASS.net (в разделе "Другие API"), НАудио, МОЛЛЮСК, G3D, и другие, которые могут это сделать.

Я думаю, вам нужно будет использовать Направленный звук (DirectX API) для этого.Он обрабатывает буферы, которые вы могли бы заполнить своими сгенерированными данными.

Может быть, что-то вроде это (здесь в обратном пути машина) поможет

У меня есть этот код, но у вас должен быть код для генерации вашего wav-файла в памяти.

Option Strict Off
Option Explicit On
Imports Microsoft.DirectX.DirectSound
Imports Microsoft.DirectX
Imports System.Threading

Public Class Form1
Const SRATE As Integer = 44100
Const FREQ As Integer = 440
Const DUR As Integer = 1

Private dsDesc As BufferDescription
Private wvFormat As WaveFormat
Private DS As Device

Dim SecondaryBuffer As Microsoft.DirectX.DirectSound.SecondaryBuffer
Dim BufferDescription As Microsoft.DirectX.DirectSound.BufferDescription
Dim DXFormat As Microsoft.DirectX.DirectSound.WaveFormat
Dim sbuf(DUR * SRATE) As Short


Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Show()
    DS = New Microsoft.DirectX.DirectSound.Device
    DS.SetCooperativeLevel(Me, CooperativeLevel.Normal)
    wvFormat.FormatTag = WaveFormatTag.Pcm
    wvFormat.Channels = 1
    wvFormat.SamplesPerSecond = SRATE
    wvFormat.BitsPerSample = 16
    wvFormat.AverageBytesPerSecond = 2 * SRATE
    wvFormat.BlockAlign = 2
    dsDesc = New BufferDescription(wvFormat)
    dsDesc.BufferBytes = 2 * DUR * SRATE
    dsDesc.Flags = 0
    Dim buff1 = PlayWave(400)
    Dim buff2 = PlayWave(600)
    buff1 = PlayWave(400)
    buff1.Play(0, Microsoft.DirectX.DirectSound.BufferPlayFlags.Default)
    Thread.Sleep(1000)
    buff1 = PlayWave(600)
    buff1.Play(0, Microsoft.DirectX.DirectSound.BufferPlayFlags.Default)
    ' End
End Sub
Function PlayWave(FREQ As Integer) As SecondaryBuffer
    ' create a buffer
    Dim dsBuffer As SecondaryBuffer
    dsBuffer = New SecondaryBuffer(dsDesc, DS)
    Dim sbuf(DUR * SRATE) As Short
    ' create tone                
    For i As Integer = 0 To DUR * SRATE
        sbuf(i) = CShort(10000 * Math.Sin(2 * Math.PI * FREQ * i / SRATE))
    Next
    ' copy to buffer
    dsBuffer.Write(0, sbuf, LockFlag.EntireBuffer)
    Return dsBuffer
End Function
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top