Play audio from a dual array

I have a problem that looks very simple at first glance, but I have big problems with it.

I have 2 dual arrays (left and right channels) containing data captured by a DAQ at 350 kHz, which I have downconverted to 44.1 kHz.

All I want to do is take these 2 arrays and play them back, but it seems like there are a lot of options for audio output i.e. directx, NAudio, etc., so I hope there might be someone who can advise me what is the best way to do it and maybe point me in the right direction!

Thanks in advance for any advice - it would be greatly appreciated.

Dave

+3


source to share


1 answer


NAudio is one of the options I've heard people mention multiple times (like you). I know this is an open source third party library. You can take a look at this.

Unfortunately, from what I collect, it seems to me that DirectX is coming out and over the years MS has changed its push to a few different things and now it seems that they are pushing people towards using XNA, which is really a complete framework that, when you do projects in XNA, can run on Windows Desktop or Xbox 360 or Windows Phone. For me, Windows Phone is not a big one as it seems like MS is not a big player in the mobile world, but the app that runs on the Xbox appeals to me. But I've seen several improved features in the XNA framework / architecture that are lacking in the regular .NET framework, including video playback and audio playback. I don't know a lot of details other than this, since I haven't gotten into XNA development yet (yet).

Also you can play them directly in .NET using System.Media.SoundPlayer without any third party library.



I found the code below that plays a simple sine wave using it. It generates sound samples and then streams it to MemoryStream

, which is then played by SoundPlayer. The SoundPlayer itself takes a stream formatted in WAV format, which I know can play stereo audio, but I don't need stereo audio, so I haven't learned how to add that to the WAV file format. What I love so much about this is that it doesn't need third party DLLs. If this method is useful to you, then here it is:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows.Forms;

public static void PlayBeep(UInt16 frequency, int msDuration, UInt16 volume = 16383)
{
    var mStrm = new MemoryStream();
    BinaryWriter writer = new BinaryWriter(mStrm);

    const double TAU = 2 * Math.PI;
    int formatChunkSize = 16;
    int headerSize = 8;
    short formatType = 1;
    short tracks = 1;
    int samplesPerSecond = 44100;
    short bitsPerSample = 16;
    short frameSize = (short)(tracks * ((bitsPerSample + 7) / 8));
    int bytesPerSecond = samplesPerSecond * frameSize;
    int waveSize = 4;
    int samples = (int)((decimal)samplesPerSecond * msDuration / 1000);
    int dataChunkSize = samples * frameSize;
    int fileSize = waveSize + headerSize + formatChunkSize + headerSize + dataChunkSize;
    // var encoding = new System.Text.UTF8Encoding();
    writer.Write(0x46464952); // = encoding.GetBytes("RIFF")
    writer.Write(fileSize);
    writer.Write(0x45564157); // = encoding.GetBytes("WAVE")
    writer.Write(0x20746D66); // = encoding.GetBytes("fmt ")
    writer.Write(formatChunkSize);
    writer.Write(formatType);
    writer.Write(tracks);
    writer.Write(samplesPerSecond);
    writer.Write(bytesPerSecond);
    writer.Write(frameSize);
    writer.Write(bitsPerSample);
    writer.Write(0x61746164); // = encoding.GetBytes("data")
    writer.Write(dataChunkSize);
    {
        double theta = frequency * TAU / (double)samplesPerSecond;
        // 'volume' is UInt16 with range 0 thru Uint16.MaxValue ( = 65 535)
        // we need 'amp' to have the range of 0 thru Int16.MaxValue ( = 32 767)
        double amp = volume >> 2; // so we simply set amp = volume / 2
        for (int step = 0; step < samples; step++)
        {
            short s = (short)(amp * Math.Sin(theta * (double)step));
            writer.Write(s);
        }
    }

    mStrm.Seek(0, SeekOrigin.Begin);
    new System.Media.SoundPlayer(mStrm).Play();
    writer.Close();
    mStrm.Close();
} // public static void PlayBeep(UInt16 frequency, int msDuration, UInt16 volume = 16383)

      

Of course, if you go with that last option, you will need to figure out how to format stereo audio as WAV and peek into (or ask) it. Happy coding!

+3


source







All Articles