Skip to content

Usage Examples for the Revoize SDK in C

← Back to Examples Overview

Example #1: Processing a Single Audio File

In this example, we'll show you how to process a single audio file using the Revoize SDK. We'll load an audio file from disk, process it with the SDK, and save the enhanced audio to a new file.

This example focuses on processing a WAV file using the Revoize SDK in a minimal setup.

WARNING

The input and output file paths, model type, and chunk size are hardcoded in this example. You may need to modify the input file path to match the location of your audio file. The input WAV file must be recorded at 48 kHz. Audio is processed in 480-sample chunks.

Here's a general sequence diagram for this example:


Include Statements

First, we need to include the necessary header files to use the Revoize SDK and process audio files. We'll use sndfile.h for reading and writing WAV files.

c
#include "revoize_sdk.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sndfile.h>

The most important line from the Revoize SDK usage perspective is:

c
#include "revoize_sdk.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sndfile.h>

This ensures we can use the Revoize SDK functions revoize_init and revoize_process.


Helper Functions

Before we start processing audio, we need some helper functions to read and write WAV files.

c
float* read_wav_file(const char* filename, size_t* num_samples) {
    SF_INFO sf_info;
    SNDFILE* file = sf_open(filename, SFM_READ, &sf_info);
    if (!file) {
        fprintf(stderr, "Could not open file: %s\n", filename);
        fprintf(stderr, "Error: %s\n", sf_strerror(NULL));
        exit(1);
    }

    float* samples = (float*)malloc(sf_info.frames * sizeof(float));
    if (!samples) {
        sf_close(file);
        fprintf(stderr, "Failed to allocate memory for samples\n");
        exit(1);
    }

    sf_count_t frames_read = sf_readf_float(file, samples, sf_info.frames);
    if (frames_read != sf_info.frames) {
        free(samples);
        sf_close(file);
        fprintf(stderr, "Failed to read audio data\n");
        exit(1);
    }

    *num_samples = frames_read;
    sf_close(file);
    return samples;
}

void write_wav_file(const char* filename, const float* samples, size_t num_samples) {
    SF_INFO sf_info;
    sf_info.samplerate = 48000;
    sf_info.channels = 1;
    sf_info.format = SF_FORMAT_WAV | SF_FORMAT_FLOAT;

    SNDFILE* file = sf_open(filename, SFM_WRITE, &sf_info);
    if (!file) {
        fprintf(stderr, "Could not create file: %s\n", filename);
        fprintf(stderr, "Error: %s\n", sf_strerror(NULL));
        exit(1);
    }

    sf_count_t frames_written = sf_writef_float(file, samples, num_samples);
    if (frames_written != num_samples) {
        sf_close(file);
        fprintf(stderr, "Failed to write audio data\n");
        exit(1);
    }

    sf_close(file);
}

Define Some Hardcoded Values

To keep this example minimalistic, we can hardcode the paths to:

  • the input WAV file
  • the output WAV file
c
    const char* input_file = "input.wav";
    const char* output_file = "output.wav";

Initialize the Revoize SDK

Before we can start processing audio, we need to initialize the Revoize SDK by calling the revoize_init function with the desired model type.

c
    // Initialize with Capella
    int result = revoize_init(REVOIZE_MODEL_CAPELLA);
    if (result != 0) {
        fprintf(stderr, "Failed to initialize Capella model\n");
        exit(1);
    }

There are various model types available in the Revoize SDK, but for this example, we are using the REVOIZE_MODEL_CAPELLA model, which is a lightweight discriminative model suitable for general denoising tasks.


Load the Input WAV File

Next, we need to load the input WAV file from disk. We use the read_wav_file helper function to read the WAV file.

c
    // Read input WAV file
    size_t num_samples;
    float* input_samples = read_wav_file(input_file, &num_samples);
    if (input_samples == NULL) {
        fprintf(stderr, "Failed to read input WAV file\n");
        exit(1);
    }

The read_wav_file function returns both the audio samples and the number of samples. The samples are stored as float values to make them compatible with the Revoize SDK's revoize_process function.


Process the Audio in Chunks

Now that we have the audio samples, we can process them in chunks using the Revoize SDK. We iterate over the audio samples in chunks of 480 samples and process each chunk using the revoize_process function.

c
    // Process the audio in chunks
    float* processed_audio = NULL;
    size_t total_processed_samples = 0;
    const size_t chunk_size = 480;
    size_t num_chunks = num_samples / chunk_size;

    for (size_t i = 0; i < num_chunks; i++) {
        // Calculate chunk boundaries
        size_t start = i * chunk_size;
        size_t end = start + chunk_size;

        // Allocate output buffer for this chunk
        float* output_chunk = (float*)malloc(chunk_size * sizeof(float));
        if (output_chunk == NULL) {
            if (processed_audio != NULL) {
                free(processed_audio);
            }
            free(input_samples);
            fprintf(stderr, "Failed to allocate output buffer for chunk\n");
            exit(1);
        }

        // Process the current chunk
        size_t output_len = chunk_size;
        result = revoize_process(&input_samples[start], chunk_size, output_chunk, &output_len);
        if (result != 0 || output_len != chunk_size) {
            free(output_chunk);
            if (processed_audio != NULL) {
                free(processed_audio);
            }
            free(input_samples);
            fprintf(stderr, "Failed to process audio chunk\n");
            exit(1);
        }

        // Reallocate and append processed chunk to the result
        float* new_processed_audio = (float*)realloc(processed_audio,
            (total_processed_samples + output_len) * sizeof(float));
        if (new_processed_audio == NULL) {
            free(output_chunk);
            if (processed_audio != NULL) {
                free(processed_audio);
            }
            free(input_samples);
            fprintf(stderr, "Failed to reallocate processed audio buffer\n");
            exit(1);
        }
        processed_audio = new_processed_audio;
        memcpy(&processed_audio[total_processed_samples], output_chunk, output_len * sizeof(float));
        total_processed_samples += output_len;

        // Free the chunk buffer
        free(output_chunk);
    }

The revoize_process function takes an input audio chunk, processes it, and stores the enhanced samples in the output buffer. We store all processed chunks in a dynamically growing buffer called processed_audio.


Save the Processed Audio to a New WAV File

Finally, we save the processed audio to a new WAV file using the write_wav_file helper function.

c
    // Write output WAV file
    write_wav_file(output_file, processed_audio, total_processed_samples);

    // Clean up
    free(input_samples);
    free(processed_audio);

Full Code Example

Below is the complete minimal source code example that demonstrates how to process a single audio file using the Revoize SDK.

c
#include "revoize_sdk.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sndfile.h>

float* read_wav_file(const char* filename, size_t* num_samples) {
    SF_INFO sf_info;
    SNDFILE* file = sf_open(filename, SFM_READ, &sf_info);
    if (!file) {
        fprintf(stderr, "Could not open file: %s\n", filename);
        fprintf(stderr, "Error: %s\n", sf_strerror(NULL));
        exit(1);
    }

    float* samples = (float*)malloc(sf_info.frames * sizeof(float));
    if (!samples) {
        sf_close(file);
        fprintf(stderr, "Failed to allocate memory for samples\n");
        exit(1);
    }

    sf_count_t frames_read = sf_readf_float(file, samples, sf_info.frames);
    if (frames_read != sf_info.frames) {
        free(samples);
        sf_close(file);
        fprintf(stderr, "Failed to read audio data\n");
        exit(1);
    }

    *num_samples = frames_read;
    sf_close(file);
    return samples;
}

void write_wav_file(const char* filename, const float* samples, size_t num_samples) {
    SF_INFO sf_info;
    sf_info.samplerate = 48000;
    sf_info.channels = 1;
    sf_info.format = SF_FORMAT_WAV | SF_FORMAT_FLOAT;

    SNDFILE* file = sf_open(filename, SFM_WRITE, &sf_info);
    if (!file) {
        fprintf(stderr, "Could not create file: %s\n", filename);
        fprintf(stderr, "Error: %s\n", sf_strerror(NULL));
        exit(1);
    }

    sf_count_t frames_written = sf_writef_float(file, samples, num_samples);
    if (frames_written != num_samples) {
        sf_close(file);
        fprintf(stderr, "Failed to write audio data\n");
        exit(1);
    }

    sf_close(file);
}

int main() {
    // -------------------------------------------------
    // 1. Hardcoded parameters and initialization
    // -------------------------------------------------
    const char* input_file = "input.wav";
    const char* output_file = "output.wav";
    const size_t chunk_size = 480;

    // Initialize with Capella
    int result = revoize_init(REVOIZE_MODEL_CAPELLA);
    if (result != 0) {
        fprintf(stderr, "Failed to initialize Capella model\n");
        exit(1);
    }

    // -------------------------------------------------
    // 2. Load the input WAV file
    // -------------------------------------------------
    size_t num_samples;
    float* input_samples = read_wav_file(input_file, &num_samples);
    if (input_samples == NULL) {
        fprintf(stderr, "Failed to read input WAV file\n");
        exit(1);
    }

    // -------------------------------------------------
    // 3. Process the audio in chunks
    // -------------------------------------------------
    float* processed_audio = NULL;
    size_t total_processed_samples = 0;
    size_t num_chunks = num_samples / chunk_size;

    for (size_t i = 0; i < num_chunks; i++) {
        // Calculate chunk boundaries
        size_t start = i * chunk_size;
        size_t end = start + chunk_size;

        // Allocate output buffer for this chunk
        float* output_chunk = (float*)malloc(chunk_size * sizeof(float));
        if (output_chunk == NULL) {
            if (processed_audio != NULL) {
                free(processed_audio);
            }
            free(input_samples);
            fprintf(stderr, "Failed to allocate output buffer for chunk\n");
            exit(1);
        }

        // Process the current chunk
        size_t output_len = chunk_size;
        result = revoize_process(&input_samples[start], chunk_size, output_chunk, &output_len);
        if (result != 0 || output_len != chunk_size) {
            free(output_chunk);
            if (processed_audio != NULL) {
                free(processed_audio);
            }
            free(input_samples);
            fprintf(stderr, "Failed to process audio chunk\n");
            exit(1);
        }

        // Reallocate and append processed chunk to the result
        float* new_processed_audio = (float*)realloc(processed_audio,
            (total_processed_samples + output_len) * sizeof(float));
        if (new_processed_audio == NULL) {
            free(output_chunk);
            if (processed_audio != NULL) {
                free(processed_audio);
            }
            free(input_samples);
            fprintf(stderr, "Failed to reallocate processed audio buffer\n");
            exit(1);
        }
        processed_audio = new_processed_audio;
        memcpy(&processed_audio[total_processed_samples], output_chunk, output_len * sizeof(float));
        total_processed_samples += output_len;

        // Free the chunk buffer
        free(output_chunk);
    }

    // -------------------------------------------------
    // 4. Save the processed audio to a new WAV file
    // -------------------------------------------------
    write_wav_file(output_file, processed_audio, total_processed_samples);

    // Clean up
    free(input_samples);
    free(processed_audio);

    return 0;
}

Example #2: Real-time Speech Enhancement

Coming Soon.