Aviv Cohn
Aviv Cohn

Reputation: 17243

What is the proper way to represent an audio sample in two bytes?

I'm working on an application that generates a sequence of numbers representing a sine wave, and saves the sine wave in a .wav file to be played as audio.

The following line of code generates the value of a single sample in the audio wave:

double sample = Math.Sin(2.0 * Math.PI * frequency * i * (1.0 / samplesPerSecond));

The resulting .wav file will be of 16 bit depth. Meaning, each sample is represented by 2 bytes (short). double however takes up 8 bytes.

What is the proper way to encode a sample into the resulting byte[], where it can only occupy 2 bytes?

Upvotes: 0

Views: 188

Answers (1)

Barmar
Barmar

Reputation: 782407

Since sine has a limited range [-1.0, 1.0], you can map the value from that range to the range of 16-bit integers [-32768, 32767].

short sample_short = SHORT_MAX * sample;

There will be some round-off error, but that's necessary to squeeze the values into the less precise data type.

The formula is only this simple because the range of sine is from -1 to 1. If you were working with some other value that has a different range, you need to normalize it first:

result = DST_TYPE_MAX * original / ORIGINAL_MAX;

This also assumes that the range of the original values is symmetric around 0. If not, you need to do:

result = DST_TYPE_MAX * (original - ORIGINAL_MIN) / (ORIGINAL_MAX-ORIGINAL_MIN)

This only works for values that have a limited range. You can't do this kind of normalization for a function like tangent, since its range is infinite.

Upvotes: 2

Related Questions