示例#1
0
文件: shusherd.c 项目: shyPi/shyPi
int audio_init(context_t *context) {
  int rc = 0;
  static const pa_sample_spec ss = {
    .format = PA_SAMPLE_S16LE,
    .rate = 44100,
    .channels = 1
  };
  int error;

  daemon_log(LOG_INFO,
             "Opening %s for input",
             context->input_device ?: "default source");

  context->pa_input = pa_simple_new(NULL,
                              "shusherd",
                              PA_STREAM_RECORD,
                              context->input_device,
                              "record",
                              &ss,
                              NULL,
                              NULL,
                              &error);
  if (!context->pa_input) {
    daemon_log(LOG_ERR, "pa_simple_new failed: %s", pa_strerror(error));
    assert(context->pa_input);
  }

  context->ebur128_state = ebur128_init(ss.channels, ss.rate, EBUR128_MODE_S);
  assert(context->ebur128_state);

  context->enable_processing = 1;

  rc = pthread_create(&context->audio_thread, NULL, audio_loop, (void *)context);
  if (rc) {
    daemon_log(LOG_ERR, "Unable to create audio thread: %d", rc);
    goto cleanup_ebur128_state;
  }

  return 0;

cleanup_ebur128_state:
  ebur128_destroy(&context->ebur128_state);
  return rc;
}

void audio_destroy(context_t *context) {
  context->enable_processing = 0;
  pthread_join(context->audio_thread, NULL);
  ebur128_destroy(&context->ebur128_state);
  pa_simple_free(context->pa_input);
}
示例#2
0
static void check_for_reset( mlt_filter filter, int channels, int frequency )
{
	mlt_properties properties = MLT_FILTER_PROPERTIES( filter );
	private_data* pdata = (private_data*)filter->child;

	if( pdata->reset )
	{
		if( pdata->r128 )
		{
			ebur128_destroy( &pdata->r128 );
		}
		pdata->r128 = 0;
		pdata->target_gain = 0.0;
		pdata->start_gain = 0.0;
		pdata->end_gain = 0.0;
		pdata->reset = 0;
		pdata->time_elapsed_ms = 0;
		pdata->prev_o_pos = -1;
		mlt_properties_set_double( properties, "out_gain", 0.0 );
		mlt_properties_set_double( properties, "in_loudness", -100.0 );
		mlt_properties_set_int( properties, "reset_count", mlt_properties_get_int( properties, "reset_count") + 1 );
	}

	if( !pdata->r128 )
	{
		pdata->r128 = ebur128_init( channels, frequency, EBUR128_MODE_I );
		ebur128_set_max_window( pdata->r128, 400 );
		ebur128_set_max_history( pdata->r128, mlt_properties_get_int( properties, "window" ) * 1000.0 );
	}
}
示例#3
0
TrackScanner::~TrackScanner()
{
    delete input;
    if (state) {
        ebur128_destroy(&state);
        state=0;
    }
}
示例#4
0
void destroy_state(struct filename_list_node *fln, gpointer unused)
{
    struct file_data *fd = (struct file_data *) fln->d;

    (void) unused;
    if (fd->st) {
        ebur128_destroy(&fd->st);
    }
}
示例#5
0
/** @This frees a upipe.
 *
 * @param upipe description structure of the pipe
 */
static void upipe_filter_ebur128_free(struct upipe *upipe)
{
    struct upipe_filter_ebur128 *upipe_filter_ebur128 =
                                 upipe_filter_ebur128_from_upipe(upipe);
    if (likely(upipe_filter_ebur128->st)) {
        ebur128_destroy(&upipe_filter_ebur128->st);
    }
    upipe_throw_dead(upipe);

    upipe_filter_ebur128_clean_output(upipe);
    upipe_filter_ebur128_clean_urefcount(upipe);
    upipe_filter_ebur128_free_void(upipe);
}
示例#6
0
文件: tests.c 项目: Drakeo/mixxx
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);
}
示例#7
0
static void filter_close( mlt_filter filter )
{
	private_data* pdata = (private_data*)filter->child;

	if( pdata )
	{
		if( pdata->r128 )
		{
			ebur128_destroy( &pdata->r128 );
		}
		free( pdata );
	}
	filter->child = NULL;
	filter->close = NULL;
	filter->parent.close = NULL;
	mlt_service_close( &filter->parent );
}
示例#8
0
文件: tests.c 项目: Drakeo/mixxx
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;
}
示例#9
0
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!
}
示例#10
0
static void check_for_reset( mlt_filter filter, int channels, int frequency )
{
	mlt_properties properties = MLT_FILTER_PROPERTIES( filter );
	private_data* pdata = (private_data*)filter->child;

	if( pdata->reset )
	{
		if( pdata->r128 )
		{
			ebur128_destroy( &pdata->r128 );
		}
		pdata->r128 = 0;
		pdata->reset = 0;
		pdata->prev_pos = -1;
		mlt_events_block( properties, filter );
		mlt_properties_set( properties, "frames_processed", "0" );
		mlt_properties_set( properties, "program", "-100.0" );
		mlt_properties_set( properties, "shortterm", "-100.0" );
		mlt_properties_set( properties, "momentary", "-100.0" );
		mlt_properties_set( properties, "range", "-1.0" );
		mlt_properties_set_int( properties, "reset_count", mlt_properties_get_int( properties, "reset_count") + 1 );
		mlt_properties_set_int( properties, "reset", 0 );
		mlt_events_unblock( properties, filter );
	}

	if( !pdata->r128 )
	{
		int mode = EBUR128_MODE_HISTOGRAM;

		if( mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "calc_program" ) )
		{
			mode |= EBUR128_MODE_I;
		}

		if( mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "calc_shortterm" ) )
		{
			mode |= EBUR128_MODE_S;
		}

		if( mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "calc_momentary" ) )
		{
			mode |= EBUR128_MODE_M;
		}

		if( mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "calc_range" ) )
		{
			mode |= EBUR128_MODE_LRA;
		}

		if( mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "calc_peak" ) )
		{
			mode |= EBUR128_MODE_SAMPLE_PEAK;
		}

		if( mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "calc_true_peak" ) )
		{
			mode |= EBUR128_MODE_TRUE_PEAK;
		}

		pdata->r128 = ebur128_init( channels, frequency,  mode );
	}
}
示例#11
0
void AnalyzerEbur128::cleanup() {
    if (isInitialized()) {
        ebur128_destroy(&m_pState);
    }
    DEBUG_ASSERT(!isInitialized());
}
示例#12
0
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;
}
示例#13
0
int
rg_scan (ddb_rg_scanner_settings_t *settings) {
    if (settings->_size != sizeof (ddb_rg_scanner_settings_t)) {
        return -1;
    }

    settings->sync_mutex = deadbeef->mutex_create ();

    if (settings->num_threads <= 0) {
        settings->num_threads = 4;
    }

    char *album_signature_tf = NULL;
    if (settings->mode == DDB_RG_SCAN_MODE_ALBUMS_FROM_TAGS) {
        album_signature_tf = deadbeef->tf_compile (album_signature);
        deadbeef->sort_track_array (NULL, settings->tracks, settings->num_tracks, album_signature, DDB_SORT_ASCENDING);
    }

    //trace ("rg_scanner: using %d thread(s)\n", settings->num_threads);

    ebur128_state **gain_state = NULL;
    ebur128_state **peak_state = NULL;

    if (settings->ref_loudness == 0) {
        settings->ref_loudness = DDB_RG_SCAN_DEFAULT_LOUDNESS;
    }

    double loudness = settings->ref_loudness;

    // allocate status array
    gain_state = calloc (settings->num_tracks, sizeof (ebur128_state *));
    peak_state = calloc (settings->num_tracks, sizeof (ebur128_state *));

    // used for joining threads
    intptr_t *rg_threads = calloc (settings->num_tracks, sizeof (intptr_t));
    track_state_t *track_states = calloc (settings->num_tracks, sizeof (track_state_t));

    // calculate gain for each track and album
    for (int i = 0; i < settings->num_tracks; ++i) {
        if (settings->progress_callback) {
            settings->progress_callback (i, settings->progress_cb_user_data);
        }
        // limit number of parallel threads
        if (i >= settings->num_threads) {
            // simple blocking mechanism: join the 'oldest' thread
            deadbeef->thread_join(rg_threads[i - settings->num_threads]);
            rg_threads[i - settings->num_threads] = 0;
        }

        if (settings->pabort && *(settings->pabort)) {
            goto cleanup;
        }

        // initialize arguments
        track_states[i].track_index = i;
        track_states[i].settings = settings;
        track_states[i].gain_state = gain_state;
        track_states[i].peak_state = peak_state;

        // run thread
        rg_threads[i] = deadbeef->thread_start(&rg_calc_thread, (void*)(&track_states[i]));
    }

    // wait for remaining threads to join
    int remaining_thread_id = settings->num_tracks - settings->num_threads;
    if (remaining_thread_id < 0) {
        remaining_thread_id = 0;
    }
    for (int i = remaining_thread_id; i < settings->num_tracks; ++i) {
        deadbeef->thread_join(rg_threads[i]);
        rg_threads[i] = 0;

        if (settings->pabort && *(settings->pabort)) {
            goto cleanup;
        }
    }

    if (settings->mode == DDB_RG_SCAN_MODE_ALBUMS_FROM_TAGS) {
        int album_start = -1;
        char current_album[1000] = "";
        char album[1000];

        ddb_tf_context_t ctx;

        ctx._size = sizeof (ctx);
        ctx.plt = NULL;
        ctx.idx = -1;
        ctx.id = -1;

        for (int i = 0; i <= settings->num_tracks; i++) {
            // set album gain when the album change is detected
            if (i < settings->num_tracks) {
                ctx.it = settings->tracks[i];
                deadbeef->tf_eval(&ctx, album_signature_tf, album, sizeof (album));
            }
            else {
                *album = 0;
            }
            album_start = _update_album_gain (settings, i, album_start, current_album, album, loudness, gain_state);
        }
    }

    if (settings->mode == DDB_RG_SOURCE_MODE_ALBUM) {
        float album_peak = 0;

        for (int i = 0; i < settings->num_tracks; ++i) {
            if (album_peak < settings->results[i].track_peak) {
                album_peak = settings->results[i].track_peak;
            }
        }

        // calculate gain of all tracks combined
        ebur128_loudness_global_multiple(gain_state, (size_t)settings->num_tracks, &loudness);

        float album_gain = -23 - (float)loudness + settings->ref_loudness - 84;

        for (int i = 0; i < settings->num_tracks; ++i) {
            settings->results[i].album_gain = album_gain;
            settings->results[i].album_peak = album_peak;
        }
    }

cleanup:
    // free thread storage
    if (rg_threads) {
        // join the still-active threads
        for (int i = 0; i < settings->num_tracks; i++) {
            if (rg_threads[i]) {
                deadbeef->thread_join (rg_threads[i]);
                rg_threads[i] = 0;
            }
        }

        free (rg_threads);
        rg_threads = NULL;
    }

    if (track_states) {
        free (track_states);
        track_states = NULL;
    }

    if (gain_state) {
        for (int i = 0; i < settings->num_tracks; ++i) {
            if (gain_state[i]) {
                ebur128_destroy (&gain_state[i]);
            }
        }
        free (gain_state);
        gain_state = NULL;
    }

    if (peak_state) {
        for (int i = 0; i < settings->num_tracks; ++i) {
            if (peak_state[i]) {
                ebur128_destroy (&peak_state[i]);
            }
        }
        free (peak_state);
        peak_state = NULL;
    }

    if (album_signature_tf) {
        deadbeef->tf_free (album_signature_tf);
        album_signature_tf = NULL;
    }

    if (settings->sync_mutex) {
        deadbeef->mutex_free (settings->sync_mutex);
        settings->sync_mutex = 0;
    }

    return 0;
}