[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