Skip to content

Commit

Permalink
added silence audio filter
Browse files Browse the repository at this point in the history
  • Loading branch information
MartinPulec committed Jul 26, 2023
1 parent b329b18 commit b634053
Show file tree
Hide file tree
Showing 3 changed files with 166 additions and 6 deletions.
1 change: 1 addition & 0 deletions Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ COMMON_OBJS = \
src/audio/filter/delay.o \
src/audio/filter/discard.o \
src/audio/filter/controlport_stats.o \
src/audio/filter/silence.o \
src/capture_filter.o \
src/capture_filter/change_pixfmt.o \
src/capture_filter/color.o \
Expand Down
12 changes: 6 additions & 6 deletions src/audio/audio_filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ struct audio_filter_info{
/// @retval 0 if initialized successfully
/// @retval <0 if error
/// @retval >0 no error but state was not returned, eg. showing help
af_result_code (*init)(struct module *mod, const char *cfg, void **state);
enum af_result_code (*init)(struct module *mod, const char *cfg, void **state);

/// @brief Frees filter
void (*done)(void *state);
Expand All @@ -76,7 +76,7 @@ struct audio_filter_info{
/// @param sample_rate sample rate
/// @retval 0 if initialized successfully
/// @retval <0 if error
af_result_code (*configure)(void *state,
enum af_result_code (*configure)(void *state,
int bps, int ch_count, int sample_rate);

/// @brief Get configured input audio format
Expand All @@ -91,20 +91,20 @@ struct audio_filter_info{
/// @param state filter state
/// @param f frame to filter, can take ownership of passed
// frame and return a different one
af_result_code (*filter)(void *state, struct audio_frame **f);
enum af_result_code (*filter)(void *state, struct audio_frame **f);
};

struct audio_filter{
const struct audio_filter_info *info;
void *state;
};

af_result_code audio_filter_init(struct module *parent, const char *name, const char *cfg,
enum af_result_code audio_filter_init(struct module *parent, const char *name, const char *cfg,
struct audio_filter *filter);

void audio_filter_destroy(struct audio_filter *state);

af_result_code audio_filter_configure(struct audio_filter *state,
enum af_result_code audio_filter_configure(struct audio_filter *state,
int bps, int ch_count, int sample_rate);

void audio_filter_get_configured_out(struct audio_filter *state,
Expand All @@ -113,7 +113,7 @@ void audio_filter_get_configured_out(struct audio_filter *state,
void audio_filter_get_configured_in(struct audio_filter *state,
int *bps, int *ch_count, int *sample_rate);

af_result_code audio_filter(struct audio_filter *state, struct audio_frame **frame);
enum af_result_code audio_filter(struct audio_filter *state, struct audio_frame **frame);

//void register_audio_filter(struct audio_filter_info *filter);

Expand Down
159 changes: 159 additions & 0 deletions src/audio/filter/silence.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
/**
* @file audio/filter/silence.c
* @author Martin Pulec <[email protected]>
*/
/*
* Copyright (c) 2023 CESNET, z. s. p. o.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, is permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of CESNET nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <assert.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>

#include "audio/audio_filter.h"
#include "audio/types.h"
#include "lib_common.h"
#include "utils/color_out.h"

enum {
MAX_CHANNELS = 16,
};

struct state_silence {
struct audio_desc desc;
size_t silence_channels[MAX_CHANNELS];
int silence_channels_count;
};

static void
usage()
{
color_printf("Audio capture " TBOLD(
"silence") " allows muting individual channels.\n\n");
color_printf("Usage:\n");
color_printf("\t" TBOLD("--audio-filter silence[:<idx1>,<idx2>]\n\n"));
color_printf("(indexed from zero)\n");
color_printf("If no index is given, all channels will be muted.\n");
}

static enum af_result_code
init(struct module *parent, const char *cfg, void **state)
{
(void) parent;
if (strlen(cfg) > 0) {
cfg++;
}
if (strcmp(cfg, "help") == 0) {
usage();
return AF_HELP_SHOWN;
}
struct state_silence *s = calloc(1, sizeof *s);

char *fmt = strdupa(cfg);
char *item = NULL;
char *end_ptr = NULL;
while ((item = strtok_r(fmt, ",", &end_ptr)) != NULL) {
assert(s->silence_channels_count < MAX_CHANNELS - 1);
s->silence_channels[s->silence_channels_count++] =
strtol(item, NULL, 10);
fmt = NULL;
}
*state = s;
return AF_OK;
}

static enum af_result_code
configure(void *state, int in_bps, int in_ch_count, int in_sample_rate)
{
struct state_silence *s = state;

s->desc.bps = in_bps;
s->desc.ch_count = in_ch_count;
s->desc.sample_rate = in_sample_rate;
return AF_OK;
}

static void
done(void *state)
{
free(state);
}

static void
get_configured_desc(void *state, int *bps, int *ch_count, int *sample_rate)
{
struct state_silence *s = state;

*bps = s->desc.bps;
*ch_count = s->desc.ch_count;
*sample_rate = s->desc.sample_rate;
}

static enum af_result_code
filter(void *state, struct audio_frame **frame)
{
struct state_silence *s = state;

if (s->silence_channels_count == 0) {
memset((*frame)->data, 0, (*frame)->data_len);
return AF_OK;
}

const int frame_size = s->desc.bps * s->desc.ch_count;
for (int i = 0; i < s->silence_channels_count; ++i) {
if (s->silence_channels[i] >= (size_t) (*frame)->ch_count) {
continue;
}
char *ptr =
(*frame)->data + s->silence_channels[i] * (*frame)->bps;
for (int j = 0; j < (*frame)->data_len; j += frame_size) {
memset(ptr, 0, (*frame)->bps);
ptr += frame_size;
}
}

return AF_OK;
}

static const struct audio_filter_info audio_filter_silence = {
.name = "silence",
.init = init,
.done = done,
.configure = configure,
.get_configured_in = get_configured_desc,
.get_configured_out = get_configured_desc,
.filter = filter,
};

REGISTER_MODULE(silence, &audio_filter_silence, LIBRARY_CLASS_AUDIO_FILTER,
AUDIO_FILTER_ABI_VERSION);

0 comments on commit b634053

Please sign in to comment.