Example #1
0
File: tests.c Project: Drakeo/mixxx
double test_loudness_range(const char* filename) {
  SF_INFO file_info;
  SNDFILE* file;
  sf_count_t nr_frames_read;

  ebur128_state* st = NULL;
  double loudness_range;
  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_LRA);
  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_range(st, &loudness_range);

  /* clean up */
  ebur128_destroy(&st);

  free(buffer);
  buffer = NULL;
  if (sf_close(file)) {
    fprintf(stderr, "Could not close input file!\n");
  }
  return loudness_range;
}
Example #2
0
/** @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;
    size_t samples;
    if (unlikely(!ubase_check(uref_sound_size(uref, &samples, NULL)))) {
        upipe_warn(upipe, "invalid sound buffer");
        uref_free(uref);
        return;
    }
    const char *channel = NULL;
    const int16_t *buf = NULL;
    if (ubase_check(uref_sound_plane_iterate(uref, &channel)) && channel) {
        if (unlikely(!ubase_check(uref_sound_plane_read_int16_t(uref,
                channel, 0, -1, &buf)))) {
            upipe_warn(upipe, "error mapping sound buffer");
            uref_free(uref);
            return;
        }

        if (unlikely((uintptr_t)buf & 1)) {
            upipe_warn(upipe, "unaligned buffer");
        }
        ebur128_add_frames_short(upipe_filter_ebur128->st, buf, samples);
        uref_sound_plane_unmap(uref, channel, 0, -1);
    }
    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);
}
Example #3
0
static void analyze_audio( mlt_filter filter, void* buffer, int samples )
{
	mlt_properties properties = MLT_FILTER_PROPERTIES( filter );
	private_data* pdata = (private_data*)filter->child;
	int result = -1;
	double loudness = 0.0;

	ebur128_add_frames_float( pdata->r128, buffer, samples );

	if( mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "calc_program" ) )
	{
		result = ebur128_loudness_global( pdata->r128, &loudness );
		if( result == EBUR128_SUCCESS && loudness != HUGE_VAL && loudness != -HUGE_VAL )
		{
			mlt_properties_set_double( properties, "program", loudness );
		}
	}

	if( mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "calc_shortterm" ) )
	{
		result = ebur128_loudness_shortterm( pdata->r128, &loudness );
		if( result == EBUR128_SUCCESS && loudness != HUGE_VAL && loudness != -HUGE_VAL )
		{
			mlt_properties_set_double( properties, "shortterm", loudness );
		}
	}

	if( mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "calc_momentary" ) )
	{
		result = ebur128_loudness_momentary( pdata->r128, &loudness );
		if( result == EBUR128_SUCCESS && loudness != HUGE_VAL && loudness != -HUGE_VAL )
		{
			mlt_properties_set_double( properties, "momentary", loudness );
		}
	}

	if( mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "calc_range" ) )
	{
		double range = 0;
		result = ebur128_loudness_range( pdata->r128, &range );
		if( result == EBUR128_SUCCESS && range != HUGE_VAL && range != -HUGE_VAL )
		{
			mlt_properties_set_double( properties, "range", range );
		}
	}

	if( mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "calc_peak" ) )
	{
		double prev_peak = 0.0;
		double max_peak = 0.0;
		int c = 0;
		for( c = 0; c < pdata->r128->channels; c++ )
		{
			double peak;
			result = ebur128_sample_peak( pdata->r128, c, &peak );
			if( result == EBUR128_SUCCESS && peak != HUGE_VAL && peak > max_peak )
			{
				max_peak = peak;
			}
			result = ebur128_prev_sample_peak( pdata->r128, c, &peak );
			if( result == EBUR128_SUCCESS && peak != HUGE_VAL && peak > prev_peak )
			{
				prev_peak = peak;
			}
		}
		mlt_properties_set_double( properties, "max_peak", 20 * log10(max_peak) );
		mlt_properties_set_double( properties, "peak", 20 * log10(prev_peak) );
	}

	if( mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "calc_true_peak" ) )
	{
		double prev_peak = 0.0;
		double max_peak = 0.0;
		int c = 0;
		for( c = 0; c < pdata->r128->channels; c++ )
		{
			double peak;
			result = ebur128_true_peak( pdata->r128, c, &peak );
			if( result == EBUR128_SUCCESS && peak != HUGE_VAL && peak > max_peak )
			{
				max_peak = peak;
			}
			result = ebur128_prev_true_peak( pdata->r128, c, &peak );
			if( result == EBUR128_SUCCESS && peak != HUGE_VAL && peak > prev_peak )
			{
				prev_peak = peak;
			}
		}
		mlt_properties_set_double( properties, "max_true_peak", 20 * log10(max_peak) );
		mlt_properties_set_double( properties, "true_peak", 20 * log10(prev_peak) );
	}

	mlt_properties_set_position( properties, "frames_processed", mlt_properties_get_position( properties, "frames_processed" ) + 1 );
}
Example #4
0
/** @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);
}
Example #5
0
void init_state_and_scan_work_item(struct filename_list_node *fln, struct scan_opts *opts)
{
    struct file_data *fd = (struct file_data *) fln->d;

    struct input_ops* ops = NULL;
    struct input_handle* ih = NULL;
    int r128_mode = EBUR128_MODE_I;
    unsigned int i;
    int *channel_map;

    int result;
    float *buffer = NULL;
    size_t nr_frames_read;

#ifdef USE_SNDFILE
    SNDFILE *outfile = NULL;
#endif

    result = open_plugin(fln->fr->raw, fln->fr->display, &ops, &ih);
    if (result) {
        g_mutex_lock(progress_mutex);
        elapsed_frames += fd->number_of_frames;
        g_cond_broadcast(progress_cond);
        g_mutex_unlock(progress_mutex);
        goto free;
    }

    if (opts->lra)
        r128_mode |= EBUR128_MODE_LRA;
    if (opts->peak) {
        if (!strcmp(opts->peak, "sample") || !strcmp(opts->peak, "all"))
            r128_mode |= EBUR128_MODE_SAMPLE_PEAK;
#ifdef USE_SPEEX_RESAMPLER
        if (!strcmp(opts->peak, "true") || !strcmp(opts->peak, "dbtp") ||
            !strcmp(opts->peak, "all"))
            r128_mode |= EBUR128_MODE_TRUE_PEAK;
#endif
    }
    if (opts->histogram)
        r128_mode |= EBUR128_MODE_HISTOGRAM;

    fd->st = ebur128_init(ops->get_channels(ih),
                          ops->get_samplerate(ih),
                          r128_mode);

    channel_map = g_malloc(fd->st->channels * sizeof(int));
    if (!ops->set_channel_map(ih, channel_map)) {
        for (i = 0; i < fd->st->channels; ++i) {
            ebur128_set_channel(fd->st, i, channel_map[i]);
        }
    }
    free(channel_map);

    if (fd->st->channels == 1 && opts->force_dual_mono) {
        ebur128_set_channel(fd->st, 0, EBUR128_DUAL_MONO);
    }

    result = ops->allocate_buffer(ih);
    if (result) abort();
    buffer = ops->get_buffer(ih);

#ifdef USE_SNDFILE
    if (opts->decode_file) {
        SF_INFO sf_info;
        memset(&sf_info, '\0', sizeof sf_info);
        sf_info.samplerate = (int) fd->st->samplerate;
        sf_info.channels = (int) fd->st->channels;
        sf_info.format = SF_FORMAT_WAV | SF_FORMAT_FLOAT;
        outfile = sf_open(opts->decode_file, SFM_WRITE, &sf_info);
        if (!outfile) {
            fprintf(stderr, "output file could not be opened\n");
            exit(EXIT_FAILURE);
        }
    }
#endif

    while ((nr_frames_read = ops->read_frames(ih))) {
        g_mutex_lock(progress_mutex);
        elapsed_frames += nr_frames_read;
        g_cond_broadcast(progress_cond);
        g_mutex_unlock(progress_mutex);
        fd->number_of_elapsed_frames += nr_frames_read;
        result = ebur128_add_frames_float(fd->st, buffer, nr_frames_read);
#ifdef USE_SNDFILE
        if (opts->decode_file) {
            if (sf_writef_float(outfile, buffer, (sf_count_t) nr_frames_read) != (sf_count_t) nr_frames_read)
                sf_perror(outfile);
        }
#endif
        if (result) abort();
    }

#ifdef USE_SNDFILE
    if (opts->decode_file) {
        sf_close(outfile);
    }
#endif

    if (fd->number_of_elapsed_frames != fd->number_of_frames) {
        if (verbose) {
            fprintf(stderr, "Warning: Could not read full file"
                            " or determine right length: "
                            "Expected: %lu Got: %lu",
                            fd->number_of_frames, fd->number_of_elapsed_frames);
        }
        g_mutex_lock(progress_mutex);
        total_frames = total_frames + fd->number_of_elapsed_frames - fd->number_of_frames;
        g_cond_broadcast(progress_cond);
        g_mutex_unlock(progress_mutex);
    }
    ebur128_loudness_global(fd->st, &fd->loudness);
    if (opts->lra) {
        result = ebur128_loudness_range(fd->st, &fd->lra);
        if (result) abort();
    }

    if ((fd->st->mode & EBUR128_MODE_SAMPLE_PEAK) == EBUR128_MODE_SAMPLE_PEAK) {
        for (i = 0; i < fd->st->channels; ++i) {
            double sp;
            ebur128_sample_peak(fd->st, i, &sp);
            if (sp > fd->peak) {
                fd->peak = sp;
            }
        }
    }
#ifdef USE_SPEEX_RESAMPLER
    if ((fd->st->mode & EBUR128_MODE_TRUE_PEAK) == EBUR128_MODE_TRUE_PEAK) {
        for (i = 0; i < fd->st->channels; ++i) {
            double tp;
            ebur128_true_peak(fd->st, i, &tp);
            if (tp > fd->true_peak) {
                fd->true_peak = tp;
            }
        }
    }
#endif
    fd->scanned = TRUE;

    if (ih) ops->free_buffer(ih);
  free:
    if (!result) ops->close_file(ih);
    if (ih) ops->handle_destroy(&ih);
}