ref: ff18ca16367d9f4326aedd97e0377494ee12ffa7
parent: 32a4066496e1211d986f6c9315e689bc12763d9f
author: Jean-Marc Valin <jean-marc.valin@usherbrooke.ca>
date: Tue Aug 9 14:48:53 EDT 2011
Adding a playback gain field to the header
--- a/src/opus_header.c
+++ b/src/opus_header.c
@@ -8,7 +8,8 @@
- Channels C (8 bits)
- Pre-skip (16 bits)
- Sampling rate (32 bits)
- - mapping (8bits, 0=single stream (mono/stereo) 1=Vorbis mapping,
+ - Gain in dB (16 bits, S7.8)
+ - Mapping (8 bits, 0=single stream (mono/stereo) 1=Vorbis mapping,
2..254: reserved, 255: multistream with no mapping)
- if (mapping != 0)
@@ -133,7 +134,11 @@
if (!read_uint32(&p, &h->input_sample_rate))
return 0;
-
+
+ if (!read_uint16(&p, &shortval))
+ return 0;
+ h->gain = (short)shortval;
+
if (!read_chars(&p, &ch, 1))
return 0;
h->channel_mapping = ch;
@@ -184,6 +189,9 @@
return 0;
if (!write_uint32(&p, h->input_sample_rate))
+ return 0;
+
+ if (!write_uint16(&p, h->gain))
return 0;
ch = h->channel_mapping;
--- a/src/opus_header.h
+++ b/src/opus_header.h
@@ -8,6 +8,7 @@
int channels; /* Number of channels: 1..255 */
int preskip;
opus_uint32 input_sample_rate;
+ int gain; /* in dB S7.8 should be zero whenever possible */
int channel_mapping;
/* The rest is only used if channel_mapping != 0 */
int nb_streams;
--- a/src/opusdec.c
+++ b/src/opusdec.c
@@ -292,7 +292,7 @@
printf ("Copyright (C) 2008-2011 Jean-Marc Valin\n");
}
-static OpusDecoder *process_header(ogg_packet *op, opus_int32 *rate, int *channels, int *preskip, int quiet)
+static OpusDecoder *process_header(ogg_packet *op, opus_int32 *rate, int *channels, int *preskip, float *gain, int quiet)
{
OpusDecoder *st;
OpusHeader header;
@@ -321,6 +321,10 @@
return NULL;
}
+ *gain = pow(20., header.gain/2560.);
+
+ if (header.gain!=0)
+ printf("Playback gain: %f (%f dB)\n", *gain, header.gain/256.);
if (!quiet)
{
fprintf (stderr, "Decoding %d Hz audio in", *rate);
@@ -413,7 +417,8 @@
int preskip=0;
int opus_serialno = -1;
SpeexResamplerState *resampler=NULL;
-
+ float gain=1;
+
enh_enabled = 1;
/*Process options*/
@@ -547,7 +552,7 @@
/*If first packet, process as OPUS header*/
if (packet_count==0)
{
- st = process_header(&op, &rate, &channels, &preskip, quiet);
+ st = process_header(&op, &rate, &channels, &preskip, &gain, quiet);
/* Converting preskip to output sampling rate */
preskip = preskip*(rate/48000.);
if (!st)
@@ -593,6 +598,13 @@
break;
}
frame_size = ret;
+ /* Apply header gain */
+ for (i=0;i<frame_size*channels;i++)
+ {
+ float tmp = gain*output[i];
+ tmp = (tmp < -32767) ? -32767 : ((tmp > 32767) ? 32767 : tmp);
+ output[i] = floor(.5+tmp);
+ }
if (print_bitrate) {
opus_int32 tmp=op.bytes;
char ch=13;
--- a/src/opusenc.c
+++ b/src/opusenc.c
@@ -509,6 +509,8 @@
header.channel_mapping = 0;
header.nb_streams = 1;
header.nb_coupled = 1;
+ /* 0 dB gain is the recommended unless you know what you're doing */
+ header.gain = 0;
header.input_sample_rate = rate;
/* Extra samples that need to be read to compensate for the pre-skip */