Upsample Audio

This article explains how to upsample an audio clip from 44.1 Khz to 48 KHz.

Source Audio

For an audio source we use the kahvi011_kennybeltrey-hydrate.mp3 file from the Internet Archive. The original audio format is MPEG Audio Layer 3, 44.1 KHz, Joint Stereo, 136 Kbps, Variable Bit Rate

Sample Code

This code takes an MP3 file with 44.1 KHz audio, and converts it to an MP3 file with 48 KHz audio using polyphase resampling method. The input and output file paths are hardcoded in the source code, no command line parsing is used.

The snippets in this section are from the simple_audio_upsample macOS sample.

Linux and Windows samples are also available:

Initialize AVBlocks

The first step in any AVBlocks application is to initialize the library. This must be done before using any other AVBlocks functionality. The TLibrary constructor initializes the library and loads the necessary codecs. The TLibrary destructor shuts the library down and releases any allocated memory, so the library is terminated when the TLibrary object goes out of scope at the end of main.

int main()
{
    TLibrary library;

    const char* inputFile  = "kahvi011_kennybeltrey-hydrate.mp3";
    const char* outputFile = "kahvi011_kennybeltrey-hydrate_48Khz.mp3";

    // transcoder will fail if output exists (by design)
    std::remove(outputFile);

Configure Transcoder and Upsample

We probe the input file with a TMediaInfo object, and create an input socket from it. The output socket is created by cloning the input socket, so it starts out with an identical configuration, and then we set the output file path on it. The transcoder is the core component that performs the actual upsampling - it takes the 44.1 KHz audio from the input and resamples it to 48 KHz using polyphase resampling for the best upsampling quality.

Probe Input and Create Sockets

First, we probe the input file and create the input socket. Then we clone it to create the output socket and set the output file path.

auto input = TMediaSocket(TMediaInfo().file(inputFile).open());

Change Sampling Rate

Next, we get the output audio stream info and change the sampling rate from 44.1 KHz to 48 KHz.

input.clone()
    .file(outputFile)
    .audioInfoRef(0, [](TAudioStreamInfo& audio) {
        // Set output sampling rate to 48 KHz
        audio.sampleRate(48000);
    })

Create and Run Transcoder

Finally, we create the transcoder, add the input and output sockets, and run the operation. The allowDemoMode(true) call allows the transcoder to work even without a valid license (useful for testing, but not recommended for production).

TTranscoder()
    .allowDemoMode(true)
    .addInput(input)
    // The output starts as a copy of the input
    .addOutput(
        input.clone()
            .file(outputFile)
            .audioInfoRef(0, [](TAudioStreamInfo& audio) {
                // Set output sampling rate to 48 KHz
                audio.sampleRate(48000);
            })
    )
    .transcode();

Complete C++ Code

Here’s the complete working example that demonstrates audio upsampling using AVBlocks. The input and output file paths are hardcoded, so no command line parsing is required.

#include <primo/avblocks/avb++.h>

#include <cstdio>
#include <print>

#include "../shim/shim23.h"

using namespace primo::avblocks::modern;

int main()
{
    TLibrary library;

    const char* inputFile  = "kahvi011_kennybeltrey-hydrate.mp3";
    const char* outputFile = "kahvi011_kennybeltrey-hydrate_48Khz.mp3";

    // transcoder will fail if output exists (by design)
    std::remove(outputFile);

    try {
        // Probe the input file and create the input socket from the probe
        auto input = TMediaSocket(TMediaInfo().file(inputFile).open());

        // Demo mode is allowed when using the demo version of the library.
        TTranscoder()
            .allowDemoMode(true)
            .addInput(input)
            // The output starts as a copy of the input
            .addOutput(
                input.clone()
                    .file(outputFile)
                    .audioInfoRef(0, [](TAudioStreamInfo& audio) {
                        // Set output sampling rate to 48 KHz
                        audio.sampleRate(48000);
                    })
            )
            .transcode();

        std::println("Output: {}", outputFile);
        return 0;

    } catch (const TAVBlocksException& ex) {
        std::println(stderr, "AVBlocks error: {}", ex.what());
        return 1;
    }
}

How to Run

See the build instructions for macOS and the simple_audio_upsample example for details.

Download the sample audio, the kahvi011_kennybeltrey-hydrate.mp3 song from the Internet Archive (MPEG Audio Layer 3, 44.1 KHz, Joint Stereo):

cd samples/darwin/simple_audio_upsample
curl -L -o kahvi011_kennybeltrey-hydrate.mp3 \
    https://archive.org/download/kahvi011/kahvi011_kennybeltrey-hydrate.mp3

Run the sample from the sample directory (the input/output file paths are relative to the working directory):

../../../bin/arm64/simple_audio_upsample    # or ../../../bin/x64/simple_audio_upsample

The upsampled output file kahvi011_kennybeltrey-hydrate_48Khz.mp3 will be created in the samples/darwin/simple_audio_upsample directory.