shithub: opus-tools

Download patch

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 */