What if... Opus codec with a 96KHz or more PCM file interpreted at 48KHz?

The Opus codec converts high-definition files to 48 KHz. I understand the reasons, but… :unamused:

Now, suppose we have a high-definition WAV file (sampled at 96, 192 or 384 KHz). Then, what if the header of the file gets modified such that the following data is interpreted at 48 KHz (i.e. slower than normal). We can then compress the audio file with Opus, which can be configured for a playback at 48 KHz. At that point, we still get the wrong pitch. But if we convert the file back to WAV, and if we recover the proper sample rate in the file header, I think we get here an interesting proof of concept for some “Opus-HD” format. Unless… Opus optimizes some frequencies in the mid-band, which would optimize the wrong range of frequencies for the original high-definition audio sequence.

Has anyone ever tried that?

OK, I did it on a Linux Mint machine. I first had to install FLAC and Opus codecs, and also Audacity. Then, I have downloaded a few 192kHz files from 2L:
http://www.2l.no/hires/

The main processing script is flac2opus.sh:

#!/bin/bash

ROOT_PATH=/localscratch/data/audio/hires

if [[ $# -ne 1 ]]; then
  echo Usage: $0 file.flac
  echo - Here are available flac files:
  ls "$ROOT_PATH/flac"
  exit 1
fi

FLAC_FILE="$ROOT_PATH/flac/$1"

if [[ ! -f "$FLAC_FILE" ]]; then
  echo Error: $FLAC_FILE, this file does not exist
  exit 1
fi

WAV_FILE=$(echo $FLAC_FILE | sed -e 's/flac/wav/g')
OPUS_FILE=$(echo $FLAC_FILE | sed -e 's/flac/opus/g')
LOSS_FILE=$(echo $WAV_FILE | sed -e 's/192kHz/opus/g')

flac -f -d "$FLAC_FILE" -o "$WAV_FILE"
./change_sample_rate "$WAV_FILE" 48000
opusenc --bitrate 256 "$WAV_FILE" "$OPUS_FILE"
opusdec "$OPUS_FILE" "$LOSS_FILE"

ls -l "$FLAC_FILE" "$WAV_FILE" "$OPUS_FILE" "$LOSS_FILE"
file "$FLAC_FILE" "$WAV_FILE" "$LOSS_FILE"
opusinfo "$OPUS_FILE"

OK, that change_sample_rate executable is a small C code compiled from change_sample_rate.c. Its task is to only change the sample rate and byte rate in the header of the .wav file:

#include <stdio.h>

#define SEEK_SAMPLE_RATE 24

int main(int argc, char **argv)
{
    FILE *wav_file;
    int old_smpl_rate, old_byte_rate;
    int new_smpl_rate, new_byte_rate;

    if (argc <= 2) {
        printf("Usage: %s file.wav sample_rate\n", argv[0]);
        return 1;
    }

    wav_file = fopen(argv[1], "r+b");

    if (wav_file != NULL) {
        fseek(wav_file, SEEK_SAMPLE_RATE, SEEK_SET);

        fread(&old_smpl_rate, sizeof(old_smpl_rate), 1, wav_file);
        fread(&old_byte_rate, sizeof(old_byte_rate), 1, wav_file);

        printf("Old sample_rate = %d\n", old_smpl_rate);
        printf("Old   byte_rate = %d\n", old_byte_rate);

        sscanf(argv[2], "%d", &new_smpl_rate);
        new_byte_rate = new_smpl_rate * (old_byte_rate / old_smpl_rate);

        printf("New sample_rate = %d\n", new_smpl_rate);
        printf("New   byte_rate = %d\n", new_byte_rate);

        fseek(wav_file, SEEK_SAMPLE_RATE, SEEK_SET);
        fwrite(&new_smpl_rate, sizeof(new_smpl_rate), 1, wav_file);
        fwrite(&new_byte_rate, sizeof(new_byte_rate), 1, wav_file);

        fclose(wav_file);
    }

    return 0;
}

Once the original FLAC file is uncompressed in a WAV file, the header is set to 48kHz, the WAV file is compressed and uncompressed with Opus, I was then able to compare both versions on Audacity.

Fortunately, Opus keeps the time alignment; I did not have align both WAV files. By inverting the lossy file data and by merging both files, I was able to subtract the lossy file to the 48kHz WAV file.

Unfortunately, the result shows quite a significant difference in dynamic portions of the music; in those time periods, the original file was producing sounds up to about -3dB, but the difference between WAV and Opus was still audible at about -40dB. This is a bit disappointing…

That being said, since the file was identified as 48kHz, I do not think the Opus file has lost many details. Maybe there is a way to keep both details and dynamic. Who knows… :slight_smile: