Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Play sound from double array

Tags:

arrays

c#

I have a problem that on the face of it looks really simple but which I'm having huge issues solving.

I have 2 double arrays (left and right channels) containing data sampled by a DAQ at 350KHz which I have downconverted to 44.1KHz.

All I want to do is to take these 2 arrays and play them but it seems as though there is a plethora of options available for outputting sound i.e. directx, NAudio etc so I'm hoping there might be someone out there who can advise me on what is the best way to do this and maybe point me in the right direction!

Thanks in advance for any advice - it will be much appreciated.

Dave

like image 349
davidpcl1977 Avatar asked Mar 01 '26 13:03

davidpcl1977


1 Answers

NAudio is one option that I've heard people mention a few times (as you did too). I know it's an open-source 3rd party library. You might want to look at that.

Unfortunately, from what I gather, it seems to me that DirectX is on its way out and MS has changed their push to a few different things over the years, and now it seems they are pushing for people to use XNA which is really an entire framework that when you make projects in XNA it can run on Windows in a Desktop environment, or Xbox 360, or Windows Phone. To me the Windows Phone is not a biggy as it seems MS isn't a big player in the mobile world, but an app that works on Xbox is appealing to me. But I've seen several better features in the XNA framework/architecture that is lacking in the regular .NET framework, including video playback and audio playback. I don't know much details beyond that tho, since I've not yet jumped into developing in XNA (yet).

Also you might want to play them directly in .NET using System.Media.SoundPlayer without any 3rd party library.

I found the code below that plays a simple sine wave, using it. It generates the sound samples and then feeds it to a MemoryStream which then is played using SoundPlayer. The SoundPlayer itself takes a Stream formatted in WAV format, which I know can play stereo sound, but I've not needed stereo sound so I have not looked into how to add that to the WAV file format. What I like so much about this is that it needs no 3rd party DLL's. 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 this last option, you'll need to figure out how to format stereo sound into the WAV format and look into that yourself (or ask about it). Happy coding!

like image 185
Edward Avatar answered Mar 03 '26 02:03

Edward



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!