0 Comments

When you play audio with NAudio, you pass an audio stream (which is an implementation of IWaveProvider) to the output device. The output device will call the Read method many times a second asking for new buffers of audio to play. When the Read method returns 0, that means we’ve reached the end of the stream, and playback will stop.

So for example, the audio file reader classes in NAudio such as WavFileReader, Mp3FileReader, AudioFileReader etc, all implement IWaveProvider and their Read method returns the number of bytes asked for until the the end is reached, after which it returns 0 and playback will stop. Because these classes also inherit from WaveStream they also support repositioning, so if you repositioned back to the start just before reaching the end, you’d be able to keep playback going for longer than the duration of the file.

But some classes in NAudio produce never-ending streams of audio. For example the SignalGenerator class is an ISampleProvider which continuously produces a signal such as a sine wave. If you pass this to a playback device (you can pass either IWaveProvider or ISampleProvider to an output device in NAudio), playback will continue indefinitely because you’ve given it a never-ending stream.

There are also some classes in NAudio whose behaviour is configurable. The MixingSampleProvider and BufferedWaveProvider are like this. If their ReadFully property is set to true, they will always return the number of bytes/samples asked for in the Read method. This is off by default with MixingSampleProvider, meaning that once you’ve reached the end of all the inputs to the mixer, playback will end. But if you turn it on, then it means you’ll continue to play silence even though the mixer has no more inputs. This can be useful if you want to dynamically add more inputs to the mixer later on.

With BufferedWaveProvider, ReadFully is set to true by default. That’s because it’s designed to help you play audio you receive over the network. If there’s audio in the buffer, it gets played, but if there’s no audio in the buffer (maybe because of poor network connectivity), we don’t want to stop playback, we just want to play silence until we’ve received some audio to play.

It’s possible to take an never-ending stream and give it a finite duration. A good example of this is the OffsetSampleProvider which can “take” a set duration of audio from an input sample provider. There are some extension methods in NAudio to make this easy to use. So for example, to get 5 seconds of a 500Hz sine wave you can do this:

var sine5Seconds = new SignalGenerator() { Gain = 0.2, Frequency = 500 }.Take(TimeSpan.FromSeconds(5));

If you play this, it will stop after 5 seconds:

using (var wo = new WaveOutEvent())
{
    wo.Init(sine5Seconds);
    wo.Play();
    while (wo.PlaybackState == PlaybackState.Playing)
    {
        Thread.Sleep(500);
    }
}

You can also go the other way, and make  make a regular wave provider endless either by extending it with silence, or by looping it. I’ve written before on how to implement looping in NAudio.

Hopefully this has helped clarify why in NAudio playback sometimes doesn’t stop when you wanted it to (you accidentally created an endless stream), or how you can can keep a single playback session running continuously without needing to keep opening and closing the output device. This allows you to easily implement a fire and forget audio playback engine where you can play sounds by adding them to a mixer, which will just produce a never-ending stream of silence if no sounds are currently active. So never-ending streams can be a good thing.

“But let justice roll on like a river, righteousness like a never-ending stream!” Amos 5:24

Want to get up to speed with the the fundamentals principles of digital audio and how to got about writing audio applications with NAudio? Be sure to check out my Pluralsight courses, Digital Audio Fundamentals, and Audio Programming with NAudio.

0 Comments

Azure offers a number of “databases” as a service. There’s SQL Azure, which is a great choice when you want a relational database that you can use with Entity Framework or query with your own custom SQL.

There’s also Azure DocumentDb which is Microsoft’s “NoSQL” offering – giving you the benefits of a schemaless document database approach, while retaining powerful querying capabilities. If you’re familiar with using NoSql databases like MongoDb then it’s an ideal choice.

And then there’s Azure Table Storage, which Microsoft describes as a “NoSQL key/attribute store”. This means that it’s got a schemaless design, and each table has rows that are made up of key value pairs. Because it’s schemaless, each row doesn’t have to contain the same keys.

But compared to DocumentDb, Table Storage is very rudimentary. There are only two indexed columns on our tables – RowKey and PartitionKey, which together uniquely identify each row. So it’s not great if you need to perform complex queries. In DocumentDb, each “document” is a JSON object that can have an arbitrarily deep structure. But in Table Storage, you’d need to manage serialization to JSON (or XML) yourself if you wanted to store complex objects or arrays inside columns.

So, compared to the more powerful capabilities of DocumentDb, Table Storage might seem a bit pointless. Does it have any advantages?

Well the main big advantage is cost. Even for the cheapest DocumentDb database, you are looking at $23 a month for a single “collection” plus a small amount more for the total data stored. This may be reasonable for production apps, but for small experiments or prototypes, it can add up quite quickly and probably force you to try to store the documents for multiple apps in the same DocumentDb collection which could get messy.

With Table Storage, you don’t pay a monthly fee, but instead pay very small amounts for the amount of data stored and the number of transactions you use. This means that for prototypes and proof of concepts it works out insanely cheap. It’s currently the only database choice in Azure that follows the “serverless” pricing model of paying only for what you actually use.

This means that Table Storage can be a good choice as a “poor man’s” NoSql database. I’ve been using it on a number of projects where I just need a couple of simple tables, and where my querying requirements are not complex. Another advantage is that it integrates very nicely with Azure Functions, making it a great choice if you want to quickly build out a “serverless” prototype.

Of course, Table Storage is also designed to be able to store huge volumes of data. So another use case it’s great for is for storing logs and diagnostic information. In fact, a several Azure services (like Azure Functions for example) use Table Storage as the backing store for their own logs.

So although Table Storage may not be the most exciting or flexible database option, if you know what it’s strengths are, it can be a useful tool to have at your disposal. There’s a helpful tutorial available if you want to get started with Table Storage using C#.

Want to learn more about how easy it is to get up and running with Azure Functions? Be sure to check out my Pluralsight course Azure Functions Fundamentals.

0 Comments

It seems every time I attempt to implement something simple in CSS I always get stuck. This time I wanted to create a div with rounded corners and a heading with a different coloured background. Something like this:

image

I attempted to build this by creating an outer div with rounded corners, and then an inner heading div with a green background. The trouble is, the inner div ends up drawing outside its containing div:

image

What’s the solution? Well it took me a long time to track down, and initially I was using a hack by rounding the corners of the heading div with a slightly smaller corner radius.

But the trick I was missing was setting overflow: hidden; on the outer div. This prevents the heading div from rendering anything outside its parent.

Here’s a JSFiddle with the way I solved it. Hope it proves helpful to someone. And let me know in the comments if there was a better way I should have tackled this.

In serverless architectures, it’s common to build your website as a SPA, meaning that you only need static website hosting. A common choice for this is Amazon S3, but if you have an Azure subscription, you may be wondering if you can use Azure Blob Storage instead.

Well, if you create a Blob Storage Account, and make a container and set it’s blobs to be publicly accessible, then you can navigate to your site by visiting a URL like: https://mystorageaccount.blob.core.windows.net/mycontainer/index.html

And this works just fine, but there are a few key limitations you need to be aware of.

First of all, although you can point a custom domain at an Azure Blob Storage account, you can’t upload your own SSL certificate. This is the top requested feature for Azure Blob Storage, and Microsoft’s response indicates they do intend to resolve this as a high priority.

Second of all, we’d rather not need to specify index.html explicitly, but Azure Blob storage doesn’t have default document support. This is another highly requested feature and so hopefully Microsoft will also address this soon, along with removing the need to specify the container name in the URL.

And there are a few other features that are desirable for a static website host, such as the ability to serve a custom 404 page.

So in its current state, Azure Blob Storage isn’t ideal for hosting a static website.

Fortunately, there is now a workaround available in the shape of Azure Functions proxies. What you can do is create an Function App and give it a proxy that passes on requests to Blob Storage.

Let’s see how to do that. In our function app, because it’s still in preview, we need to explicitly enable proxies:

image

And I’ll create two proxies. The first, will redirect the base URL to the index.html in my static hosting blob container:

image

And the second will forward every additional request for any other path directly to the blob container. That’s achieved with the special {*restOfPath} syntax which matches any path.

image

With that in place, I now can directly access my static website by visiting the URL of the function app.

What’s more, Azure Function apps support custom domains, so I can go in and configure some domain name I own to point at the function app.

image

Azure Function Apps also allow you to upload SSL certificates, so as well as solving the default document issue, and removing the need for the container name in the path, this also is a way to use HTTPS on custom domains. So with Azure Functions proxies you can work around most of the major limitations of static hosting on Azure Blob Storage.

Obviously you will pay for a function execution for each file that’s requested, but remember that you get 1 million free function executions a month, so you may not end up paying anything for most websites.

Want to learn more about how easy it is to get up and running with Azure Functions? Be sure to check out my Pluralsight course Azure Functions Fundamentals.

0 Comments

A few years back I wrote a blog post explaining how you can perform “input driven resampling” with NAudio using the ACM resampler codec installed on your system.

Input driven resampling is when you have blocks of audio you are receiving (say from the microphone) and you want to pass them to the resampler, and ask it to give you however many samples that input turns into.

For playing back audio, generally output driven resampling is what you want, and NAudio has lots of good options available for that. But a common use case for input driven resampling is where you want to save the audio you’re recording from the microphone in a different format (usually a lower sample rate) than the microphone is providing the audio samples in.

Now the input driven ACM resampling option is fine if you’re working on desktop windows which has the ACM resampler, and if your audio is 16 bit. But if you’re dealing with IEEE floating point audio and you’re on Windows Azure or a non-windows platform, you might not have access to built-in codecs.

So in this post, I want to explain how we can use a C# port of the Cockos WDL resampler to perform input driven resampling of our audio.

I made the port so NAudio could provide the WdlResamplingSampleProvider which provides a fully managed output-driven resampler.

But I never made the underlying WdlResampler class public. That’s because I wanted to clean up it’s interface a bit before sharing it. However, it is fully self-contained, so there is no difficulty just copying the code from this class and including it in your own project.

Let’s see how we can use it. I’ll simulate input driven resampling, by reading 1000 samples at a time from an input file, but this audio could just as easily be coming from the soundcard via WasapiCapture. And then I’ll pass each block of input samples into the WdlResampler, and ask to read out whatever’s available. I’ll use an output buffer that’s bigger than I need so I’ll always fully read out resampled audio.

There’s a few points worth noting here.

  • I’m using AudioFileReader so the input audio is floating point samples. The WdlResampler only works with floating point
  • The WdlResampler has a SetFeedMode method that allows us to specify we are in input driven mode
  • In this example I’m downsampling to 16kHz (assuming the input file is >16kHz)
  • The WdlResampler uses counts of sample “frames” rather than number of samples. In a stereo file, a sample frame is two samples – a left and a right sample. I haven’t checked if the resampler supports changing the channel count – I suspect not, but you can easily change channel count as a separate step.

 

int outRate = 16000;
var inFile = @"E:\Some Input File.mp3";
var outFile = @"E:\Resampled Output File.wav";

using (var reader = new AudioFileReader(inFile))
using (var writer = new WaveFileWriter(outFile, WaveFormat.CreateIeeeFloatWaveFormat(outRate, reader.WaveFormat.Channels)))
{
    var read = 0;
    var buffer = new float[1000];
    var resampler = new WdlResampler();
    resampler.SetMode(true, 2, false);
    resampler.SetFilterParms();
    resampler.SetFeedMode(true); // input driven
    resampler.SetRates(reader.WaveFormat.SampleRate, outRate);

    
    while ((read = reader.Read(buffer, 0, buffer.Length)) > 0)
    {
        int framesAvailable = read / reader.WaveFormat.Channels;
        float[] inBuffer;
        int inBufferOffset;
        int inNeeded = resampler.ResamplePrepare(framesAvailable, writer.WaveFormat.Channels, out inBuffer, out inBufferOffset);
     
        Array.Copy(buffer,0,inBuffer,inBufferOffset,inNeeded * reader.WaveFormat.Channels);
        
        int inAvailable = inNeeded;
        float[] outBuffer = new float[2000]; // plenty big enough
        int framesRequested = outBuffer.Length / writer.WaveFormat.Channels;
        int outAvailable = resampler.ResampleOut(outBuffer, 0, inAvailable, framesRequested, writer.WaveFormat.Channels);

        writer.WriteSamples(outBuffer, 0, outAvailable * writer.WaveFormat.Channels);
    }
}

So that’s how you can perform input driven resampling in fully managed C#. Admittedly it is a little more cumbersome than the equivalent output driven code:

int outRate = 16000;
var inFile = @"E:\some input file.mp3";
var outFile = @"E:\resampled wdl.wav";
using (var reader = new AudioFileReader(inFile))
{
    var resampler = new WdlResamplingSampleProvider(reader, outRate);
    WaveFileWriter.CreateWaveFile16(outFile, resampler);
}

But hopefully this helps people who are stuck with how to perform input driven resampling of IEEE floating point samples on systems without built-in codecs. I’ve provided a gist with the full code here.

And I’ll probably make the WdlResampler class in NAudio public in the future so you won’t need to take a copy.

Note – if you are using WasapiCapture or WasapiLoopbackCapture and you are wondering how to turn the incoming byte array into a float array, then check out my article here for some techniques – the WaveBuffer one is probably the best choice.

Want to get up to speed with the the fundamentals principles of digital audio and how to got about writing audio applications with NAudio? Be sure to check out my Pluralsight courses, Digital Audio Fundamentals, and Audio Programming with NAudio.