Question

I have been pointed towards NAudio as possibly allowing me to do this. However, if it cannot, I would appreciate suggestions of libraries that can. I am currently working in C#/WPF, but comfortable calling other C/C++ libraries.

I am receiving a continuous buffer of audio samples (mono). Type: 16-bit signed integer. Rate: 16 kHz. I will need to hold 1-2 hours of buffer data (230 MB). I want to save this buffer to disk so I can retrieve it later.

Need to be able to play parts of this buffer while still capturing, e.g.:

@0s, Buffer.StartRecording()
@30s, handle = Buffer.Play(20,25) //Plays the buffer from 20 - 25 s
@50s, handle1 = Buffer.Play(20,25)
@51s, handle2 = Buffer.Play(20,25) //Playing two parts of the buffer at the same time.
@52s, handle1.Stop() //Buffer1 stops playing after having played for 2 seconds.

I should be able to start playing a sound that hasn't finished writing yet:

@0s, Buffer.StartRecording()
@25s, handle = Buffer.Play(20,30) //Plays the buffer from 20 - 30 s
@30s, //Buffer has played halfway through (currently, play marker is at 25 s
@35s, //Buffer playing finishes.

Need to be able to mask out parts of played-back buffer, e.g.:

bufferMaskStep = 1 //seconds
bufferMask = [1, 0, 0.5, 1, 0.1] //the volumes at each time step
Buffer.Play(20, 25, bufferMask, bufferMaskStep)

I see that NAudio offers WaveStream, but apparently WaveStream.Write is not supported. I could manage appending to a byte buffer myself, and copy sections out of it when I want to play them, but I am wondering if there is an out-of-the-box solution.

The gist of what I'm doing is making a loop pedal.

Was it helpful?

Solution

In NAudio, BufferedWaveProvider is designed so you can be reading audio from it (e.g. playing from it) while adding audio into it (e.g. received from a soundcard or over the network).

OTHER TIPS

If you're writing raw audio data to the disk as a long-term buffer, then you are going to have to handle it yourself.

You have two basic options, depending on how you want to isolate the read and write operations: create a single FileStream object with read/write access to the file, or create multiple FileStream objects - one for writing, and however many you need for reading.

The first option is the simplest. When you create your FileStream object, make sure it has ReadWrite access:

FileStream datafile = new FileStream(filename, FileMode.Create, FileAccess.ReadWrite);

You can use that Stream to append data to the file by setting the Position to the end of the file before calling Write. Similarly to read data from a position in the file you set the Position to the offset into the file of the data you want to read, then call Read.

The other option is a bit more difficult, but gives you a certain amount of separation between the read and write operations. When you create each FileStream object you need to specify the FileShare option you need to allow multiple views of the same file.

In this scenario you would create a write Stream with the following options:

FileStream dataWriter = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.Read);

When you want to read from the file create a new FileStream with read access like so:

FileStream dataReader = new FileStream(filename, FileMode.Open, FileAccess.Read);

Storing the data is the (relatively) simple part. The fun part is getting the data in and out of the store.

I will update this answer shortly with some more details. Let me play with it for a while.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top