52#include <unordered_map>
63static_assert(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__,
64 "The code below assumes little endianness.");
79template<
int BPS>
static int32_t
load_sample(
const char *data);
82 return *
reinterpret_cast<const int8_t *
>(data);
86 return *
reinterpret_cast<const int16_t *
>(data);
91 memcpy(&in_value, data, 3);
93 if ((in_value & 1U<<23U) != 0U) {
94 in_value |= 0xFF000000U;
101 return *
reinterpret_cast<const int32_t *
>(data);
116 int sample_stride = 1)
120 const int byte_stride =
BPS * sample_stride;
121 for (
int i = 0; i < sample_count; i += 1) {
122 double val =
load_sample<BPS>(channel_data + i * byte_stride) /
static_cast<double>(1U << (
BPS * CHAR_BIT - 1U));
124 *peak =
max(fabs(
val), *peak);
127 double average = sum / sample_count;
129 double sumMeanSquare = 0.0;
131 for (
int i = 0; i < sample_count; i += 1) {
132 sumMeanSquare += pow(
load_sample<BPS>(channel_data + i * byte_stride) /
static_cast<double>(1U << (
BPS * CHAR_BIT - 1U))
136 double averageMeanSquare = sumMeanSquare / sample_count;
137 double rootMeanSquare = sqrt(averageMeanSquare);
139 return rootMeanSquare;
153 int sample_count =
frame->get_data_len(channel) /
frame->get_bps();
154 switch (
frame->get_bps()) {
171 assert(channel < frame->ch_count);
172 char *data =
frame->data + channel *
frame->bps;
174 switch (
frame->bps) {
190 return a1.
bps == a2.
bps &&
208 channel->sample_rate,
228 static thread_local uint32_t last_rand = 0;
232 last_rand = (last_rand * 1664525) + 1013904223L;
233 int triangle_dither = last_rand >> (32 - shift);
234 last_rand = (last_rand * 1664525) + 1013904223L;
235 triangle_dither -= last_rand >> (32 - shift);
243 if(INT32_MAX -
abs(
val) < (1 << shift) - 1 + (1 << (shift - 1)))
244 return val / (1 << shift);
247 val += 1 << (shift - 1);
249 val -= 1 << (shift - 1);
251 return (
val + triangle_dither) / (1 << shift);
254#define NO_DITHER_PARAM "no-dither"
256 " Disable audio dithering when reducing bit depth\n");
258void change_bps(
char *out,
int out_bps,
const char *in,
int in_bps,
int in_len ) {
260 change_bps2(out, out_bps, in, in_bps, in_len, dither);
263void change_bps2(
char *out,
int out_bps,
const char *in,
int in_bps,
int in_len ,
bool dither)
265 assert ((
unsigned int) out_bps <=
sizeof(int32_t));
266 static_assert(-2>>1 == -1,
"Implementation-defined behavior doesn't work as expected by the implementation.");
268 if (in_bps == out_bps ) {
269 memcpy(out, in, in_len);
273 if (in_bps < out_bps ) {
274 for (
int i = 0; i < in_len / in_bps; i++) {
276 int32_t out_value = in_value << (out_bps * 8 - in_bps * 8);
286 const int downshift = in_bps * 8 - out_bps * 8;
287 for (
int i = 0; i < in_len / in_bps; i++) {
297 for (
int i = 0; i < in_len / in_bps; i++) {
299 int32_t out_value = in_value >> (in_bps * 8 - out_bps * 8);
306void copy_channel(
char *out,
const char *in,
int bps,
int in_len ,
int out_channel_count)
308 int samples = in_len /
bps;
311 assert(out_channel_count > 0);
316 out += in_len * out_channel_count;
317 for (i = samples; i > 0 ; --i) {
321 for (j = out_channel_count + 0; j > 0; --j) {
323 memmove(out, in,
bps);
329 assert((
unsigned int)
frame->max_size >= (
unsigned int)
frame->data_len * new_channel_count /
frame->ch_count);
334void demux_channel(
char *out,
char *in,
int bps,
int in_len,
int in_stream_channels,
int pos_in_stream)
336 int samples = in_len / (in_stream_channels *
bps);
341 in += pos_in_stream *
bps;
343 for (i = 0; i < samples; ++i) {
344 memcpy(out, in,
bps);
347 in += in_stream_channels *
bps;
352void remux_channel(
char *out,
const char *in,
int bps,
int in_len,
int in_stream_channels,
int out_stream_channels,
int pos_in_stream,
int pos_out_stream)
354 int samples = in_len / (in_stream_channels *
bps);
359 in += pos_in_stream *
bps;
360 out += pos_out_stream *
bps;
362 for (i = 0; i < samples; ++i) {
363 memcpy(out, in,
bps);
365 out +=
bps * out_stream_channels;
366 in +=
bps * in_stream_channels;
371void mux_channel(
char *out,
const char *in,
int bps,
int in_len,
int out_stream_channels,
int pos_in_stream,
double scale)
373 int samples = in_len /
bps;
378 out += pos_in_stream *
bps;
381 for (i = 0; i < samples; ++i) {
382 memcpy(out, in,
bps);
385 out += out_stream_channels *
bps;
389 for (i = 0; i < samples; ++i) {
397 out += out_stream_channels *
bps;
402void mux_and_mix_channel(
char *out,
const char *in,
int bps,
int in_len,
int out_stream_channels,
int pos_in_stream,
double scale)
408 out += pos_in_stream *
bps;
410 for(i = 0; i < in_len /
bps; i++) {
414 int32_t new_value = (double)in_value * scale + out_value;
419 out += out_stream_channels *
bps;
423void remux_and_mix_channel(
char *out,
const char *in,
int bps,
int frames,
int in_stream_channels,
int out_stream_channels,
int in_channel,
int out_channel,
double scale)
429 out += out_channel *
bps;
430 in += in_channel *
bps;
432 for(i = 0; i < frames; i++) {
436 int32_t new_value = (double)in_value * scale + out_value;
440 in += in_stream_channels *
bps;
441 out += out_stream_channels *
bps;
450 data += pos_in_stream *
BPS;
452 for (
int i = 0; i < sample_count; i++) {
455 vol += labs(in_value);
458 return static_cast<double>(vol) / sample_count / ((1U << (
BPS * 8U - 1U)));
461double get_avg_volume(
char *data,
int bps,
int sample_count,
int stream_channels,
int pos_in_stream) {
484 const float *inf = (
const float *)(
const void *) in;
485 int32_t *outi = (int32_t *)(
void *) out;
486 int items =
len /
sizeof(int32_t);
489 float sample = *inf++;
490 if(sample > 1.0) sample = 1.0;
491 if(sample < -1.0) sample = -1.0;
498 const int32_t *ini = (
const int32_t *)(
const void *) in;
499 float *outf = (
float *)(
void *) out;
500 int items =
len /
sizeof(int32_t);
503 *outf++ = (float) *ini++ / (
float) INT_MAX;
517 const auto *inch =
reinterpret_cast<const int8_t *
>(in);
518 uint8_t *outch = (uint8_t *) out;
519 int items = in_len /
sizeof(int8_t);
522 int8_t in_value = *inch++;
523 uint8_t out_value = (int) 128 + in_value;
524 *outch++ = out_value;
558#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
559 memcpy(out, &out_value,
bps);
561 memcpy(out, (
char *) &out_value + 4 -
bps,
bps);
569 for (
int i = 0; i < in_len / channel_count /
bps; ++i) {
570 for (
int ch = 0; ch < channel_count; ++ch) {
571 memcpy(out_ch[ch] + (ptrdiff_t) i *
bps, in,
bps);
581 for (
int ch = 0; ch < channel_count; ++ch) {
582 assert((uintptr_t) out_ch[ch] % 4 == 0);
585 for (
int i = 0; i < in_len / channel_count; ++i) {
586 for (
int ch = 0; ch < channel_count; ++ch) {
588 INT8_MIN + *(
const uint8_t *) in;
589 *(
float *) (
void *) (out_ch[ch] +
591 (
float)
val / -INT8_MIN;
596 for (
int i = 0; i < in_len / channel_count / in_bps; ++i) {
597 for (
int ch = 0; ch < channel_count; ++ch) {
599 memcpy((
char *) &
val + 4 - in_bps, in, in_bps);
600 *(
float *) (
void *) (out_ch[ch] +
602 (
float)
val / (-1.0F * INT32_MIN);
613 vector<char *> out_ch(channel_count);
614 for (
int i = 0; i < channel_count; ++i) {
615 out_ch[i] = out + (ptrdiff_t) in_len / channel_count * i;
622 if (
frame->data_len + data_len > (
size_t)
frame->max_size) {
627 memcpy(
frame->data +
frame->data_len, data, data_len);
628 frame->data_len += data_len;
635 memcpy(ret, src,
sizeof *ret);
645 thread_local string str =
desc;
656 if (strcmp(str,
"help") == 0) {
658 color_printf(
TBOLD(
"\t{channels=<num>|bps=<bits_per_sample>|sample_rate=<rate>}*\n"));
659 color_printf(
"\t\tmultiple options can be separated by a colon\n");
663 unique_ptr<char[]> arg_copy(
new char[strlen(str) + 1]);
664 char *arg = arg_copy.get();
667 char *save_ptr =
nullptr;
670 while (
char *
item = strtok_r(tmp,
",:", &save_ptr)) {
671 const char *
const val = strchr(
item,
'=') + 1;
677 "Invalid number of channels %s! Valid "
683 const int bps = stoi(
val);
688 LOG(
LOG_LEVEL_WARNING) <<
"bps is in bits per sample but a value not divisible by 8 was given.\n";
698 <<
"Invalid sample_rate " << rate
699 <<
"! Valid range 1-"
717 char *save_ptr = NULL;
720 char *tmp = ptr = strdup(cfg);
723 while((
item = strtok_r(ptr,
",", &save_ptr))) {
726 if(isdigit(
item[0])) {
741 tmp = ptr = strdup(cfg);
743 while((
item = strtok_r(ptr,
",", &save_ptr))) {
746 assert(strchr(
item,
':') != NULL);
748 if(isdigit(
item[0])) {
753 if(!isdigit(strchr(
item,
':')[1])) {
758 int dst = atoi(strchr(
item,
':') + 1);
784 for(
int i = 0; i <
size; ++i) {
792 for(
int i = 0; i <
size; ++i) {
793 for(
int j = 0; j <
sizes[i]; ++j) {
805 for (
int i = 0; i <
size; ++i) {
806 for (
int j = 0; j <
sizes[i]; ++j) {
811 for (
int i = 0; i <
size; ++i) {
812 for (
int j = 0; j <
sizes[i]; ++j) {
829 char **volume_start,
char *volume_end)
833 snprintf(*volume_start, volume_end - *volume_start,
", ");
835 const double rms_dbfs = 20.0 * log(rms) / log(10.0);
836 const double peak_dbfs = 20.0 * log(peak) / log(10.0);
838 snprintf(*volume_start, volume_end - *volume_start,
840 format_color, rms_dbfs, format_color, peak_dbfs);
struct video_frame * frame
This file contains definition of some common audio types.
int color_printf(const char *format,...)
static __device__ vec2 abs(const vec2 &v)
void log_msg(int level, const char *format,...)
#define LOG_LEVEL_INFO
normal reporting
#define LOG_LEVEL_ERROR
general errors
#define LOG_LEVEL_FATAL
errors that prevent UG run
#define LOG_LEVEL_WARNING
less severe errors
std::unordered_map< std::string, std::string > commandline_params
#define ADD_TO_PARAM(param, doc)
#define IS_KEY_PREFIX(tok, key)
expands to true value if <k> from tok in format <k>=<v> is prefix of key
long long unit_evaluate(const char *str, const char **endptr)
Audio channel is a non-owning view on audio_frame2 isolating one channel.
struct used to comunicate with audio capture/playback device
void compute_contributors()
void mux_and_mix_channel(char *out, const char *in, int bps, int in_len, int out_stream_channels, int pos_in_stream, double scale)
void copy_channel(char *out, const char *in, int bps, int in_len, int out_channel_count)
int32_t load_sample< 4 >(const char *data)
struct audio_desc audio_desc_from_frame(const struct audio_frame *frame)
int32_t load_sample< 2 >(const char *data)
void remux_and_mix_channel(char *out, const char *in, int bps, int frames, int in_stream_channels, int out_stream_channels, int in_channel, int out_channel, double scale)
bool parse_channel_map_cfg(struct channel_map *channel_map, const char *cfg)
int32_t load_sample< 3 >(const char *data)
bool audio_desc_eq(struct audio_desc a1, struct audio_desc a2)
void interleaved2noninterleaved_float(char **out_ch, const char *in, int in_bps, int in_len, int channel_count)
void signed2unsigned(char *out, const char *in, int in_len)
void audio_channel_demux(const audio_frame2 *frame, int index, audio_channel *channel)
static double get_avg_volume_helper(const char *data, int sample_count, int stream_channels, int pos_in_stream)
void float2int(char *out, const char *in, int len)
void audio_frame_write_desc(struct audio_frame *f, struct audio_desc desc)
static int32_t format_from_in_bps(const char *in, int bps)
reads sample at specified BPS and returns it in i32 container (not scaled)
bool append_audio_frame(struct audio_frame *frame, char *data, size_t data_len)
double get_avg_volume(char *data, int bps, int sample_count, int stream_channels, int pos_in_stream)
void mux_channel(char *out, const char *in, int bps, int in_len, int out_stream_channels, int pos_in_stream, double scale)
static void format_to_out_bps(char *out, int bps, int32_t out_value)
void change_bps2(char *out, int out_bps, const char *in, int in_bps, int in_len, bool dither)
changes bps with option to specify whether or not do the dithering
void interleaved2noninterleaved2(char **out_ch, const char *in, int bps, int in_len, int channel_count)
void interleaved2noninterleaved(char *out, const char *in, int bps, int in_len, int channel_count)
static double calculate_rms_helper(const char *channel_data, int sample_count, double *peak, int sample_stride=1)
Calculates mean and peak RMS from audio samples.
int32_t load_sample< 1 >(const char *data)
void audio_frame_multiply_channel(struct audio_frame *frame, int new_channel_count)
void demux_channel(char *out, char *in, int bps, int in_len, int in_stream_channels, int pos_in_stream)
void change_bps(char *out, int out_bps, const char *in, int in_bps, int in_len)
double calculate_rms(audio_frame2 *frame, int channel, double *peak)
Calculates mean and peak RMS from audio samples.
void remux_channel(char *out, const char *in, int bps, int in_len, int in_stream_channels, int out_stream_channels, int pos_in_stream, int pos_out_stream)
int32_t downshift_with_dither(int32_t val, int shift)
void format_audio_channel_volume(int chan_idx, double rms, double peak, const char *format_color, char **volume_start, char *volume_end)
format per channel incrementally volume string (eg. "[0]-18.00/-14.99, [1] -18.00/-14....
int parse_audio_format(const char *str, struct audio_desc *ret)
struct audio_frame * audio_frame_copy(const struct audio_frame *src, bool keep_size)
void int2float(char *out, const char *in, int len)
static int32_t load_sample(const char *data)
struct audio_desc audio_desc_from_audio_channel(const audio_channel *channel)
const char * audio_desc_to_cstring(struct audio_desc desc)