/** @internal @This sets the input flow definition.
 *
 * @param upipe description structure of the pipe
 * @param flow flow definition packet
 * @return an error code
 */
static int upipe_filter_ebur128_set_flow_def(struct upipe *upipe,
                                             struct uref *flow)
{
    struct upipe_filter_ebur128 *upipe_filter_ebur128 =
                                 upipe_filter_ebur128_from_upipe(upipe);
    if (flow == NULL)
        return UBASE_ERR_INVALID;
    UBASE_RETURN(uref_flow_match_def(flow, "sound.s16."))
    uint8_t channels, planes;
    uint64_t rate;
    if (unlikely(!ubase_check(uref_sound_flow_get_rate(flow, &rate))
            || !ubase_check(uref_sound_flow_get_channels(flow, &channels))
            || !ubase_check(uref_sound_flow_get_planes(flow, &planes))
            || planes != 1)) {
        return UBASE_ERR_INVALID;
    }

    struct uref *flow_dup;
    if (unlikely((flow_dup = uref_dup(flow)) == NULL)) {
        upipe_throw_fatal(upipe, UBASE_ERR_ALLOC);
        return UBASE_ERR_ALLOC;
    }

    if (unlikely(upipe_filter_ebur128->st)) {
        //ebur128_destroy(&upipe_filter_ebur128->st);
        ebur128_change_parameters(upipe_filter_ebur128->st, channels, rate);
    } else {
    upipe_filter_ebur128->st = ebur128_init(channels, rate,
            EBUR128_MODE_LRA | EBUR128_MODE_I | EBUR128_MODE_HISTOGRAM);
    }

    upipe_filter_ebur128_store_flow_def(upipe, flow_dup);
    return UBASE_ERR_NONE;
}
Exemple #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 );
	}
}
Exemple #3
0
bool AnalyzerEbur128::initialize(TrackPointer tio,
        int sampleRate, int totalSamples) {
    if (isDisabledOrLoadStoredSuccess(tio) || totalSamples == 0) {
        return false;
    }
    if (!isInitialized()) {
        m_pState = ebur128_init(2u,
                static_cast<unsigned long>(sampleRate),
                EBUR128_MODE_I);
    }
    return isInitialized();
}
Exemple #4
0
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);
}
Exemple #5
0
/** @internal @This sets the input flow definition.
 *
 * @param upipe description structure of the pipe
 * @param flow flow definition packet
 * @return an error code
 */
static int upipe_filter_ebur128_set_flow_def(struct upipe *upipe,
                                             struct uref *flow)
{
    struct upipe_filter_ebur128 *upipe_filter_ebur128 =
                                 upipe_filter_ebur128_from_upipe(upipe);
    if (flow == NULL)
        return UBASE_ERR_INVALID;

    enum upipe_filter_ebur128_fmt fmt;
    const char *def;
    UBASE_RETURN(uref_flow_get_def(flow, &def))
    if (!ubase_ncmp(def, "sound.s16."))
        fmt = UPIPE_FILTER_EBUR128_SHORT;
    else if (!ubase_ncmp(def, "sound.s32."))
        fmt = UPIPE_FILTER_EBUR128_INT;
    else if (!ubase_ncmp(def, "sound.f32."))
        fmt = UPIPE_FILTER_EBUR128_FLOAT;
    else if (!ubase_ncmp(def, "sound.f64."))
        fmt = UPIPE_FILTER_EBUR128_DOUBLE;
    else
        return UBASE_ERR_INVALID;

    uint64_t rate;
    if (unlikely(!ubase_check(uref_sound_flow_get_rate(flow, &rate))
            || !ubase_check(uref_sound_flow_get_channels(flow,
                    &upipe_filter_ebur128->channels))
            || !ubase_check(uref_sound_flow_get_planes(flow,
                    &upipe_filter_ebur128->planes))))
        return UBASE_ERR_INVALID;

    struct uref *flow_dup;
    if (unlikely((flow_dup = uref_dup(flow)) == NULL)) {
        upipe_throw_fatal(upipe, UBASE_ERR_ALLOC);
        return UBASE_ERR_ALLOC;
    }
    upipe_filter_ebur128->fmt = fmt;

    if (unlikely(upipe_filter_ebur128->st)) {
        //ebur128_destroy(&upipe_filter_ebur128->st);
        ebur128_change_parameters(upipe_filter_ebur128->st,
                                  upipe_filter_ebur128->channels, rate);
    } else {
        upipe_filter_ebur128->st =
            ebur128_init(upipe_filter_ebur128->channels, rate,
            EBUR128_MODE_LRA | EBUR128_MODE_I | EBUR128_MODE_HISTOGRAM);
    }

    upipe_filter_ebur128_store_flow_def(upipe, flow_dup);
    return UBASE_ERR_NONE;
}
Exemple #6
0
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);
}
Exemple #7
0
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;
}
Exemple #8
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!
}
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 );
	}
}
Exemple #10
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);
}
Exemple #11
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;
}
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;
}
Exemple #13
0
void TrackScanner::run()
{
    bool ffmpegIsFloat=false;
    #ifdef FFMPEG_FOUND
    FfmpegInput *ffmpeg=new FfmpegInput(file);
    if (*ffmpeg) {
        input=ffmpeg;
        ffmpegIsFloat=ffmpeg->isFloatCodec();
    } else {
        delete ffmpeg;
        ffmpeg=0;
    }
    #endif

    #if MPG123_FOUND
    if (file.endsWith(".mp3", Qt::CaseInsensitive) && (!input || !ffmpegIsFloat)) {
        Mpg123Input *mpg123=new Mpg123Input(file);
        if (*mpg123) {
            input=mpg123;
            #ifdef FFMPEG_FOUND
            if (ffmpeg) {
                delete ffmpeg;
            }
            #endif
        } else {
            delete mpg123;
        }
    }
    #endif

    if (!input) {
        setFinishedStatus(false);
        return;
    }

    state=ebur128_init(input->channels(), input->sampleRate(), EBUR128_MODE_M|EBUR128_MODE_I|EBUR128_MODE_SAMPLE_PEAK);

    int *channelMap=new int [state->channels];
    if (input->setChannelMap(channelMap)) {
        for (unsigned int i = 0; i < state->channels; ++i) {
            ebur128_set_channel(state, i, channelMap[i]);
        }
    }

    delete [] channelMap;

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

    size_t numFramesRead=0;
    size_t totalRead=0;
    input->allocateBuffer();
    while ((numFramesRead = input->readFrames())) {
        if (abortRequested) {
            setFinishedStatus(false);
            return;
        }
        totalRead+=numFramesRead;
        emit progress((int)((totalRead*100.0/input->totalFrames())+0.5));
        if (ebur128_add_frames_float(state, input->buffer(), numFramesRead)) {
            setFinishedStatus(false);
            return;
        }
    }

    if (abortRequested) {
        setFinishedStatus(false);
        return;
    }

    ebur128_loudness_global(state, &data.loudness);
//     if (opts->lra) {
//         result = ebur128_loudness_range(ebur, &lra);
//         if (result) abort();
//     }

    if (EBUR128_MODE_SAMPLE_PEAK==(state->mode & EBUR128_MODE_SAMPLE_PEAK)) {
        for (unsigned i = 0; i < state->channels; ++i) {
            double sp;
            ebur128_sample_peak(state, i, &sp);
            if (sp > data.peak) {
                data.peak = sp;
            }
        }
    }
    if (EBUR128_MODE_TRUE_PEAK==(state->mode & EBUR128_MODE_TRUE_PEAK)) {
        for (unsigned i = 0; i < state->channels; ++i) {
            double tp;
            ebur128_true_peak(state, i, &tp);
            if (tp > data.truePeak) {
                data.truePeak = tp;
            }
        }
    }
    setFinishedStatus(true);
}
Exemple #14
0
void
rg_calc_thread(void *ctx) {
    DB_decoder_t *dec = NULL;
    DB_fileinfo_t *fileinfo = NULL;

    char *buffer = NULL;
    char *bufferf = NULL;

    track_state_t *st = (track_state_t *)ctx;
    if (st->settings->pabort && *(st->settings->pabort)) {
        return;
    }
    if (deadbeef->pl_get_item_duration (st->settings->tracks[st->track_index]) <= 0) {
        st->settings->results[st->track_index].scan_result = DDB_RG_SCAN_RESULT_INVALID_FILE;
        return;
    }


    deadbeef->pl_lock ();
    dec = (DB_decoder_t *)deadbeef->plug_get_for_id (deadbeef->pl_find_meta (st->settings->tracks[st->track_index], ":DECODER"));
    deadbeef->pl_unlock ();

    if (dec) {
        fileinfo = dec->open (DDB_DECODER_HINT_RAW_SIGNAL);

        if (fileinfo && dec->init (fileinfo, DB_PLAYITEM (st->settings->tracks[st->track_index])) != 0) {
            st->settings->results[st->track_index].scan_result = DDB_RG_SCAN_RESULT_FILE_NOT_FOUND;
            goto error;
        }

        if (fileinfo) {
            st->gain_state[st->track_index] = ebur128_init(fileinfo->fmt.channels, fileinfo->fmt.samplerate, EBUR128_MODE_I);
            st->peak_state[st->track_index] = ebur128_init(fileinfo->fmt.channels, fileinfo->fmt.samplerate, EBUR128_MODE_SAMPLE_PEAK);

            // speaker mask mapping from WAV to EBUR128
            static const int chmap[18] = {
                EBUR128_LEFT,
                EBUR128_RIGHT,
                EBUR128_CENTER,
                EBUR128_UNUSED,
                EBUR128_LEFT_SURROUND,
                EBUR128_RIGHT_SURROUND,
                EBUR128_LEFT_SURROUND,
                EBUR128_RIGHT_SURROUND,
                EBUR128_CENTER,
                EBUR128_LEFT_SURROUND,
                EBUR128_RIGHT_SURROUND,
                EBUR128_CENTER,
                EBUR128_LEFT_SURROUND,
                EBUR128_CENTER,
                EBUR128_RIGHT_SURROUND,
                EBUR128_LEFT_SURROUND,
                EBUR128_CENTER,
                EBUR128_RIGHT_SURROUND,
            };

            uint32_t channelmask = fileinfo->fmt.channelmask;

            // first 18 speaker positions are known, the rest will be marked as UNUSED
            int ch = 0;
            for (int i = 0; i < 32 && ch < fileinfo->fmt.channels; i++) {
                if (i < 18) {
                    if (channelmask & (1<<i))
                    {
                        ebur128_set_channel (st->gain_state[st->track_index], ch, chmap[i]);
                        ebur128_set_channel (st->peak_state[st->track_index], ch, chmap[i]);
                        ch++;
                    }
                }
                else {
                    ebur128_set_channel (st->gain_state[st->track_index], ch, EBUR128_UNUSED);
                    ebur128_set_channel (st->peak_state[st->track_index], ch, EBUR128_UNUSED);
                    ch++;
                }
            }

            int samplesize = fileinfo->fmt.channels * fileinfo->fmt.bps / 8;

            int bs = 2000 * samplesize;
            ddb_waveformat_t fmt;

            buffer = malloc (bs);

            if (!fileinfo->fmt.is_float) {
                bufferf = malloc (2000 * sizeof (float) * fileinfo->fmt.channels);
                memcpy (&fmt, &fileinfo->fmt, sizeof (fmt));
                fmt.bps = 32;
                fmt.is_float = 1;
            }
            else {
                bufferf = buffer;
            }

            int eof = 0;
            for (;;) {
                if (eof) {
                    break;
                }
                if (st->settings->pabort && *(st->settings->pabort)) {
                    break;
                }

                int sz = dec->read (fileinfo, buffer, bs); // read one block

                deadbeef->mutex_lock (st->settings->sync_mutex);
                int samplesize = fileinfo->fmt.channels * (fileinfo->fmt.bps >> 3);
                int numsamples = sz / samplesize;
                st->settings->cd_samples_processed += numsamples * 44100 / fileinfo->fmt.samplerate;
                deadbeef->mutex_unlock (st->settings->sync_mutex);

                if (sz != bs) {
                    eof = 1;
                }

                // convert from native output to float,
                // only if the input is not float already
                if (!fileinfo->fmt.is_float) {
                    deadbeef->pcm_convert (&fileinfo->fmt, buffer, &fmt, bufferf, sz);
                }

                int frames = sz / samplesize;

                ebur128_add_frames_float (st->gain_state[st->track_index], (float*) bufferf, frames); // collect data
                ebur128_add_frames_float (st->peak_state[st->track_index], (float*) bufferf, frames); // collect data
            }
        }

        if (!st->settings->pabort || !(*(st->settings->pabort))) {
            // calculating track peak
            // libEBUR128 calculates peak per channel, so we have to pick the highest value
            double tr_peak = 0;
            double ch_peak = 0;
            int res;
            for (int ch = 0; ch < fileinfo->fmt.channels; ++ch) {
                res = ebur128_sample_peak (st->peak_state[st->track_index], ch, &ch_peak);
                //trace ("rg_scanner: peak for ch %d: %f\n", ch, ch_peak);
                if (ch_peak > tr_peak) {
                    //trace ("rg_scanner: %f > %f\n", ch_peak, tr_peak);
                    tr_peak = ch_peak;
                }
            }

            st->settings->results[st->track_index].track_peak = (float) tr_peak;

            // calculate track loudness
            double loudness = st->settings->ref_loudness;
            ebur128_loudness_global (st->gain_state[st->track_index], &loudness);

            /*
             * EBUR128 sets the target level to -23 LUFS = 84dB
             * -> -23 - loudness = track gain to get to 84dB
             *
             * The old implementation of RG used 89dB, most people still use that
             * -> the above + (loudness - 84) = track gain to get to 89dB (or user specified)
             */
            st->settings->results[st->track_index].track_gain = -23 - loudness + st->settings->ref_loudness - 84;
        }
    }

error:
    // clean up
    if (fileinfo) {
        dec->free (fileinfo);
    }

    if (buffer && buffer != bufferf) {
        free (buffer);
        buffer = NULL;
    }

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