double test_true_peak(const char* filename) { SF_INFO file_info; SNDFILE* file; sf_count_t nr_frames_read; int i; ebur128_state* st = NULL; double true_peak; double max_true_peak = -HUGE_VAL; double* buffer; memset(&file_info, '\0', sizeof(file_info)); file = sf_open(filename, SFM_READ, &file_info); if (!file) { fprintf(stderr, "Could not open file %s!\n", filename); return 0.0; } st = ebur128_init((unsigned) file_info.channels, (unsigned) file_info.samplerate, EBUR128_MODE_TRUE_PEAK); if (file_info.channels == 5) { ebur128_set_channel(st, 0, EBUR128_LEFT); ebur128_set_channel(st, 1, EBUR128_RIGHT); ebur128_set_channel(st, 2, EBUR128_CENTER); ebur128_set_channel(st, 3, EBUR128_LEFT_SURROUND); ebur128_set_channel(st, 4, EBUR128_RIGHT_SURROUND); } buffer = (double*) malloc(st->samplerate * st->channels * sizeof(double)); while ((nr_frames_read = sf_readf_double(file, buffer, (sf_count_t) st->samplerate))) { ebur128_add_frames_double(st, buffer, (size_t) nr_frames_read); } for (i = 0; i < file_info.channels; i++) { ebur128_true_peak(st, (unsigned)i, &true_peak); if (true_peak > max_true_peak) max_true_peak = true_peak; } /* clean up */ ebur128_destroy(&st); free(buffer); buffer = NULL; if (sf_close(file)) { fprintf(stderr, "Could not close input file!\n"); } return 20 * log10(max_true_peak); }
double test_global_loudness(const char* filename) { SF_INFO file_info; SNDFILE* file; sf_count_t nr_frames_read; ebur128_state* st = NULL; double gated_loudness; double* buffer; memset(&file_info, '\0', sizeof(file_info)); file = sf_open(filename, SFM_READ, &file_info); if (!file) { fprintf(stderr, "Could not open file %s!\n", filename); return 0.0; } st = ebur128_init((unsigned) file_info.channels, (unsigned) file_info.samplerate, EBUR128_MODE_I); if (file_info.channels == 5) { ebur128_set_channel(st, 0, EBUR128_LEFT); ebur128_set_channel(st, 1, EBUR128_RIGHT); ebur128_set_channel(st, 2, EBUR128_CENTER); ebur128_set_channel(st, 3, EBUR128_LEFT_SURROUND); ebur128_set_channel(st, 4, EBUR128_RIGHT_SURROUND); } buffer = (double*) malloc(st->samplerate * st->channels * sizeof(double)); while ((nr_frames_read = sf_readf_double(file, buffer, (sf_count_t) st->samplerate))) { ebur128_add_frames_double(st, buffer, (size_t) nr_frames_read); } ebur128_loudness_global(st, &gated_loudness); /* clean up */ ebur128_destroy(&st); free(buffer); buffer = NULL; if (sf_close(file)) { fprintf(stderr, "Could not close input file!\n"); } return gated_loudness; }
int main(int ac, const char* av[]) { SF_INFO file_info; SNDFILE* file; sf_count_t nr_frames_read; ebur128_state* state = NULL; double* buffer; double loudness; if (ac != 2) { exit(1); //ERROR CODE 1: Exactly one input file is expected. } state = malloc((size_t) sizeof(ebur128_state*)); memset(&file_info, '\0', sizeof(file_info)); file = sf_open(av[1], SFM_READ, &file_info); state = ebur128_init((unsigned) file_info.channels, (unsigned) file_info.samplerate, EBUR128_MODE_I); buffer = (double*) malloc(state->samplerate * state->channels * sizeof(double)); while ((nr_frames_read = sf_readf_double(file, buffer, (sf_count_t) state->samplerate))) { ebur128_add_frames_double(state, buffer, (size_t) nr_frames_read); } ebur128_loudness_global(state, &loudness); fprintf(stdout, "%.2f\n", loudness); free(buffer); buffer = NULL; if (sf_close(file)) { exit(2); //ERROR CODE 2: File wasn't able to be closed. } ebur128_destroy(&state); free(state); return 0; // ERROR CODE 0: No errors! }
/** @internal @This handles input. * * @param upipe description structure of the pipe * @param uref uref structure * @param upump_p reference to upump structure */ static void upipe_filter_ebur128_input(struct upipe *upipe, struct uref *uref, struct upump **upump_p) { struct upipe_filter_ebur128 *upipe_filter_ebur128 = upipe_filter_ebur128_from_upipe(upipe); double loud = 0, lra = 0, global = 0; if (unlikely(upipe_filter_ebur128->output_flow == NULL)) { upipe_err_va(upipe, "invalid input"); uref_free(uref); return; } size_t samples; uint8_t sample_size; if (unlikely(!ubase_check(uref_sound_size(uref, &samples, &sample_size)))) { upipe_warn(upipe, "invalid sound buffer"); uref_free(uref); return; } void *buf = NULL; const char *channel = NULL; if (upipe_filter_ebur128->planes == 1) { if (ubase_check(uref_sound_plane_iterate(uref, &channel)) && channel) { if (unlikely(!ubase_check(uref_sound_plane_read_void(uref, channel, 0, -1, (const void **)&buf)))) { upipe_warn(upipe, "error mapping sound buffer"); uref_free(uref); return; } } } else { buf = malloc(sample_size * upipe_filter_ebur128->channels * samples); if (buf == NULL) { upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); uref_free(uref); return; } if (!ubase_check(uref_sound_interleave(uref, (uint8_t *)buf, 0, samples, sample_size, upipe_filter_ebur128->planes))) { upipe_warn(upipe, "error mapping sound buffer"); uref_free(uref); return; } } if (unlikely((uintptr_t)buf & 1)) upipe_warn(upipe, "unaligned buffer"); switch (upipe_filter_ebur128->fmt) { case UPIPE_FILTER_EBUR128_SHORT: ebur128_add_frames_short(upipe_filter_ebur128->st, (short *)buf, samples); break; case UPIPE_FILTER_EBUR128_INT: ebur128_add_frames_int(upipe_filter_ebur128->st, (int *)buf, samples); break; case UPIPE_FILTER_EBUR128_FLOAT: ebur128_add_frames_float(upipe_filter_ebur128->st, (float *)buf, samples); break; case UPIPE_FILTER_EBUR128_DOUBLE: ebur128_add_frames_double(upipe_filter_ebur128->st, (double *)buf, samples); break; default: upipe_warn_va(upipe, "unknown sample format %d", upipe_filter_ebur128->fmt); break; } if (upipe_filter_ebur128->planes == 1) uref_sound_plane_unmap(uref, channel, 0, -1); else free(buf); ebur128_loudness_momentary(upipe_filter_ebur128->st, &loud); ebur128_loudness_range(upipe_filter_ebur128->st, &lra); ebur128_loudness_global(upipe_filter_ebur128->st, &global); uref_ebur128_set_momentary(uref, loud); uref_ebur128_set_lra(uref, lra); uref_ebur128_set_global(uref, global); upipe_verbose_va(upipe, "loud %f lra %f global %f", loud, lra, global); upipe_filter_ebur128_output(upipe, uref, upump_p); }
int main(int ac, const char* av[]) { SF_INFO file_info; SNDFILE* file; sf_count_t nr_frames_read; ebur128_state** sts = NULL; double* buffer; double loudness; int i; if (ac < 2) { fprintf(stderr, "usage: %s FILENAME...\n", av[0]); exit(1); } sts = malloc((size_t) (ac - 1) * sizeof(ebur128_state*)); for (i = 0; i < ac - 1; ++i) { memset(&file_info, '\0', sizeof(file_info)); file = sf_open(av[i + 1], SFM_READ, &file_info); sts[i] = ebur128_init((unsigned) file_info.channels, (unsigned) file_info.samplerate, EBUR128_MODE_I); /* example: set channel map (note: see ebur128.h for the default map) */ if (file_info.channels == 5) { ebur128_set_channel(sts[i], 0, EBUR128_LEFT); ebur128_set_channel(sts[i], 1, EBUR128_RIGHT); ebur128_set_channel(sts[i], 2, EBUR128_CENTER); ebur128_set_channel(sts[i], 3, EBUR128_LEFT_SURROUND); ebur128_set_channel(sts[i], 4, EBUR128_RIGHT_SURROUND); } buffer = (double*) malloc(sts[i]->samplerate * sts[i]->channels * sizeof(double)); while ((nr_frames_read = sf_readf_double(file, buffer, (sf_count_t) sts[i]->samplerate))) { ebur128_add_frames_double(sts[i], buffer, (size_t) nr_frames_read); } ebur128_loudness_global(sts[i], &loudness); fprintf(stderr, "%.2f LUFS, %s\n", loudness, av[i + 1]); free(buffer); buffer = NULL; if (sf_close(file)) { fprintf(stderr, "Could not close input file!\n"); } } ebur128_loudness_global_multiple(sts, (size_t) ac - 1, &loudness); fprintf(stderr, "-----------\n%.2f LUFS\n", loudness); /* clean up */ for (i = 0; i < ac - 1; ++i) { ebur128_destroy(&sts[i]); } free(sts); return 0; }
int main(int argc, const char *argv[]) { struct sockaddr_in addr, graphiteAddr; int addrlen, sock, packetLength, graphiteSocket; struct ip_mreq mreq; uint8_t packet[1452]; //uint16_t sequenceNumber; //uint32_t timestamp; double audioPayload[480]; ebur128_state* state = NULL; double shortTermLoudness; uint32_t frameCounter = 0; char graphiteOutputBuffer[200]; if (argc != 4) { fprintf(stderr, "Argument Error!\n"); fprintf(stderr, "Correct usage: axialufsgraphite <MC Livewire IP> <Graphite Server IP> <Graphite Metric>\n"); fprintf(stderr, "Example: axialufsgraphite 239.192.2.169 127.0.0.1 Studio442PGM\n"); return 1; } const char *axiaLivewireIP = argv[1]; const char *graphiteServerIP = argv[2]; const char *graphiteMetric = argv[3]; /* setup graphite socket */ graphiteSocket = socket(AF_INET,SOCK_STREAM,0); memset(&graphiteAddr, 0, sizeof(graphiteAddr)); graphiteAddr.sin_family = AF_INET; graphiteAddr.sin_port = htons(2003); inet_pton(AF_INET, graphiteServerIP, &(graphiteAddr.sin_addr)); connect(graphiteSocket,(struct sockaddr *) &graphiteAddr, sizeof(graphiteAddr)); /* setup axia socket (multicast UDP listener) */ sock = socket(AF_INET, SOCK_DGRAM, 0); int reuse = 1; if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &reuse, sizeof(reuse)) == -1) { fprintf(stderr, "setsockopt: %d\n", errno); return 1; } memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(5004); addr.sin_addr.s_addr = inet_addr(axiaLivewireIP); addrlen = sizeof(addr); if (bind(sock, (struct sockaddr*) &addr, sizeof(addr)) == -1) { fprintf(stderr, "bind: %d\n", errno); return 1; } mreq.imr_multiaddr.s_addr = inet_addr(axiaLivewireIP); mreq.imr_interface.s_addr = htonl(INADDR_ANY); setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&mreq, sizeof(mreq)); /* init ebur128 state */ state = malloc((size_t) sizeof(ebur128_state*)); state = ebur128_init((unsigned) 2, (unsigned) 48000, EBUR128_MODE_S); /* main loop */ while(1){ packetLength = recvfrom(sock, packet, sizeof(packet), 0, (struct sockaddr *) &addr, (socklen_t *) &addrlen); //sequenceNumber = (packet[2] << 8 | packet[3]); //timestamp = (packet[4] << 24 | packet[5] << 16 | packet[6] << 8 | packet[7]); for (int i = 12; i < packetLength; i += 3) { int32_t audioPCM = ((packet[i] << 16) | (packet[i + 1] << 8) | (packet[i + 2])); if (audioPCM & 0x800000) audioPCM |= ~0xffffff; // Convert to signed PCM. double audioFloat = (audioPCM * (1.0 / 0x7fffff)); // Convert to float. audioPayload[((i - 12) / 3)] = audioFloat; } ebur128_add_frames_double(state, audioPayload, (size_t) ((packetLength - 12) / 6)); frameCounter += ((packetLength - 12) / 6); if (frameCounter >= 47999) { frameCounter = 0; ebur128_loudness_shortterm(state, &shortTermLoudness); shortTermLoudness = shortTermLoudness <= -70. ? -70. : shortTermLoudness; sprintf(graphiteOutputBuffer, "%s %f %d\n", graphiteMetric, shortTermLoudness, (int) time(NULL)); send(graphiteSocket, graphiteOutputBuffer, (strlen(graphiteOutputBuffer)), 0); } } free(state); return 0; }