Reputation: 17243
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
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