[SCM] libgroove/upstream: use the compand filter to allow setting the gain to > 1.0

andrewrk-guest at users.alioth.debian.org andrewrk-guest at users.alioth.debian.org
Mon Mar 17 02:20:50 UTC 2014


The following commit has been merged in the upstream branch:
commit 0b6ce95e05f2ffb2122e5e3334bd7732ce47b56d
Author: Andrew Kelley <superjoe30 at gmail.com>
Date:   Sat Feb 8 19:52:08 2014 -0500

    use the compand filter to allow setting the gain to > 1.0
    
    closes #45

diff --git a/example/playlist.c b/example/playlist.c
index 15eaf7c..5267e9f 100644
--- a/example/playlist.c
+++ b/example/playlist.c
@@ -3,12 +3,18 @@
 #include <grooveplayer/player.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
+
+static int usage(const char *exe) {
+    fprintf(stderr, "Usage: %s [--volume 1.0] file1 file2 ...\n", exe);
+    return 1;
+}
 
 int main(int argc, char * argv[]) {
-    if (argc < 2) {
-        fprintf(stderr, "Usage: %s file1 file2 ...\n", argv[0]);
-        return 1;
-    }
+    // parse arguments
+    const char *exe = argv[0];
+    if (argc < 2) return usage(exe);
+
     groove_init();
     atexit(groove_finish);
     groove_set_logging(GROOVE_LOG_INFO);
@@ -23,15 +29,26 @@ int main(int argc, char * argv[]) {
     groove_player_attach(player, playlist);
 
     for (int i = 1; i < argc; i += 1) {
-        char * filename = argv[i];
-        struct GrooveFile * file = groove_file_open(filename);
-        if (!file) {
-            fprintf(stderr, "Not queuing %s\n", filename);
-            continue;
+        char *arg = argv[i];
+        if (arg[0] == '-' && arg[1] == '-') {
+            arg += 2;
+            if (i + 1 >= argc) {
+                return usage(exe);
+            } else if (strcmp(arg, "volume") == 0) {
+                double volume = atof(argv[++i]);
+                groove_playlist_set_volume(playlist, volume);
+            } else {
+                return usage(exe);
+            }
+        } else {
+            struct GrooveFile * file = groove_file_open(arg);
+            if (!file) {
+                fprintf(stderr, "Not queuing %s\n", arg);
+                continue;
+            }
+            groove_playlist_insert(playlist, file, 1.0, NULL);
         }
-        groove_playlist_insert(playlist, file, 1.0, NULL);
     }
-    groove_playlist_play(playlist);
 
     union GroovePlayerEvent event;
     struct GroovePlaylistItem *item;
diff --git a/groove/playlist.c b/groove/playlist.c
index fc3dd14..c8d7b05 100644
--- a/groove/playlist.c
+++ b/groove/playlist.c
@@ -56,6 +56,7 @@ struct GroovePlaylistPrivate {
     AVFilterGraph *filter_graph;
     AVFilterContext *abuffer_ctx;
     AVFilterContext *volume_ctx;
+    AVFilterContext *compand_ctx;
     AVFilterContext *asplit_ctx;
 
     // this mutex applies to the variables in this block
@@ -249,8 +250,16 @@ static int audio_decode_frame(struct GroovePlaylist *playlist, struct GrooveFile
     return max_data_size;
 }
 
+static const double dB_scale = 0.1151292546497023; // log(10) * 0.05
+
+static double gain_to_dB(double gain) {
+    return log(gain) / dB_scale;
+}
+
 // abuffer -> volume -> asplit for each audio format
 //                     -> aformat -> abuffersink
+// if the volume gain is > 1.0, we use a compand filter instead
+// for soft limiting.
 static int init_filter_graph(struct GroovePlaylist *playlist, struct GrooveFile *file) {
     struct GroovePlaylistPrivate *p = (struct GroovePlaylistPrivate *) playlist;
     struct GrooveFilePrivate *f = (struct GrooveFilePrivate *) file;
@@ -267,6 +276,7 @@ static int init_filter_graph(struct GroovePlaylist *playlist, struct GrooveFile
 
     AVFilter *abuffer = avfilter_get_by_name("abuffer");
     AVFilter *volume = avfilter_get_by_name("volume");
+    AVFilter *compand = avfilter_get_by_name("compand");
     AVFilter *asplit = avfilter_get_by_name("asplit");
     AVFilter *aformat = avfilter_get_by_name("aformat");
     AVFilter *abuffersink = avfilter_get_by_name("abuffersink");
@@ -299,13 +309,12 @@ static int init_filter_graph(struct GroovePlaylist *playlist, struct GrooveFile
     // save the volume value so we can compare later and check
     // whether we have to reconstruct the graph
     p->filter_volume = p->volume;
-    // if volume is not equal to 1.0, create volume filter
+    // if volume is < 1.0, create volume filter
+    //             == 1.0, do not create a filter
+    //              > 1.0, create a compand filter (for soft limiting)
     double vol = p->volume;
-    if (vol > 1.0) vol = 1.0;
     if (vol < 0.0) vol = 0.0;
-    if (vol == 1.0) {
-        p->volume_ctx = NULL;
-    } else {
+    if (vol < 1.0) {
         snprintf(p->strbuf, sizeof(p->strbuf), "volume=%f", vol);
         av_log(NULL, AV_LOG_INFO, "volume: %s\n", p->strbuf);
         err = avfilter_graph_create_filter(&p->volume_ctx, volume, NULL,
@@ -320,6 +329,31 @@ static int init_filter_graph(struct GroovePlaylist *playlist, struct GrooveFile
             return err;
         }
         audio_src_ctx = p->volume_ctx;
+    } else if (vol > 1.0) {
+        double attack = 0.1;
+        double decay = 0.2;
+        const char *points = "-2/-2";
+        double soft_knee = 0.02;
+        double gain = gain_to_dB(vol);
+        double volume_param = 0.0;
+        double delay = 0.2;
+        snprintf(p->strbuf, sizeof(p->strbuf), "%f:%f:%s:%f:%f:%f:%f",
+                attack, decay, points, soft_knee, gain, volume_param, delay);
+        av_log(NULL, AV_LOG_INFO, "compand: %s\n", p->strbuf);
+        err = avfilter_graph_create_filter(&p->compand_ctx, compand, NULL,
+                p->strbuf, NULL, p->filter_graph);
+        if (err < 0) {
+            av_log(NULL, AV_LOG_ERROR, "error initializing compand filter\n");
+            return err;
+        }
+        err = avfilter_link(audio_src_ctx, 0, p->compand_ctx, 0);
+        if (err < 0) {
+            av_log(NULL, AV_LOG_ERROR, "unable to link filters\n");
+            return err;
+        }
+        audio_src_ctx = p->compand_ctx;
+    } else {
+        p->volume_ctx = NULL;
     }
 
     // if only one sink, no need for asplit

-- 
libgroove packaging



More information about the pkg-multimedia-commits mailing list