Ejemplo n.º 1
0
static inline gboolean
check_default (AudioConvertCtx * ctx, const GstAudioFormatInfo * fmt)
{
  if (!DOUBLE_INTERMEDIATE_FORMAT (ctx)) {
    return GST_AUDIO_FORMAT_INFO_FORMAT (fmt) == GST_AUDIO_FORMAT_S32;
  } else {
    return GST_AUDIO_FORMAT_INFO_FORMAT (fmt) == GST_AUDIO_FORMAT_F64;
  }
}
Ejemplo n.º 2
0
static inline gboolean
check_default (AudioConvertCtx * ctx, AudioConvertFmt * fmt)
{
  if (!DOUBLE_INTERMEDIATE_FORMAT (ctx)) {
    return (fmt->width == 32 && fmt->depth == 32 &&
        fmt->endianness == G_BYTE_ORDER && fmt->sign == TRUE);
  } else {
    return (fmt->width == 64 && fmt->endianness == G_BYTE_ORDER);
  }
}
Ejemplo n.º 3
0
static gint
audio_convert_get_func_index (AudioConvertCtx * ctx, AudioConvertFmt * fmt)
{
  gint index = 0;

  if (fmt->is_int) {
    index += (fmt->width / 8 - 1) * 4;
    index += fmt->endianness == G_LITTLE_ENDIAN ? 0 : 2;
    index += fmt->sign ? 1 : 0;
    index += (ctx->ns == NOISE_SHAPING_NONE) ? 0 : 24;
  } else {
    /* this is float/double */
    index = 16;
    index += (fmt->width == 32) ? 0 : 2;
    index += (fmt->endianness == G_LITTLE_ENDIAN) ? 0 : 1;
    index += (DOUBLE_INTERMEDIATE_FORMAT (ctx)) ? 4 : 0;
  }

  return index;
}
Ejemplo n.º 4
0
static gint
audio_convert_get_func_index (AudioConvertCtx * ctx,
    const GstAudioFormatInfo * fmt)
{
  gint index = 0;

  if (GST_AUDIO_FORMAT_INFO_IS_INTEGER (fmt)) {
    index += (GST_AUDIO_FORMAT_INFO_WIDTH (fmt) / 8 - 1) * 4;
    index += GST_AUDIO_FORMAT_INFO_IS_LITTLE_ENDIAN (fmt) ? 0 : 2;
    index += GST_AUDIO_FORMAT_INFO_IS_SIGNED (fmt) ? 1 : 0;
    index += (ctx->ns == NOISE_SHAPING_NONE) ? 0 : 24;
  } else {
    /* this is float/double */
    index = 16;
    index += (GST_AUDIO_FORMAT_INFO_WIDTH (fmt) == 32) ? 0 : 2;
    index += GST_AUDIO_FORMAT_INFO_IS_LITTLE_ENDIAN (fmt) ? 0 : 1;
    index += (DOUBLE_INTERMEDIATE_FORMAT (ctx)) ? 4 : 0;
  }

  return index;
}
Ejemplo n.º 5
0
gboolean
audio_convert_convert (AudioConvertCtx * ctx, gpointer src,
    gpointer dst, gint samples, gboolean src_writable)
{
  guint insize, outsize, size;
  gpointer outbuf, tmpbuf;
  guint intemp = 0, outtemp = 0, biggest;

  g_return_val_if_fail (ctx != NULL, FALSE);
  g_return_val_if_fail (src != NULL, FALSE);
  g_return_val_if_fail (dst != NULL, FALSE);
  g_return_val_if_fail (samples >= 0, FALSE);

  if (samples == 0)
    return TRUE;

  insize = ctx->in.unit_size * samples;
  outsize = ctx->out.unit_size * samples;

  /* find biggest temp buffer size */
  size = (DOUBLE_INTERMEDIATE_FORMAT (ctx)) ? sizeof (gdouble)
      : sizeof (gint32);

  if (!ctx->in_default)
    intemp = gst_util_uint64_scale (insize, size * 8, ctx->in.width);
  if (!ctx->mix_passthrough || !ctx->out_default)
    outtemp = gst_util_uint64_scale (outsize, size * 8, ctx->out.width);
  biggest = MAX (intemp, outtemp);

  /* see if one of the buffers can be used as temp */
  if ((outsize >= biggest) && (ctx->out.unit_size <= size))
    tmpbuf = dst;
  else if ((insize >= biggest) && src_writable && (ctx->in.unit_size >= size))
    tmpbuf = src;
  else {
    if (biggest > ctx->tmpbufsize) {
      ctx->tmpbuf = g_realloc (ctx->tmpbuf, biggest);
      ctx->tmpbufsize = biggest;
    }
    tmpbuf = ctx->tmpbuf;
  }

  /* start conversion */
  if (!ctx->in_default) {
    /* check if final conversion */
    if (!(ctx->out_default && ctx->mix_passthrough))
      outbuf = tmpbuf;
    else
      outbuf = dst;

    /* unpack to default format */
    ctx->unpack (src, outbuf, ctx->in_scale, samples * ctx->in.channels);

    src = outbuf;
  }

  if (!ctx->mix_passthrough) {
    /* check if final conversion */
    if (!ctx->out_default)
      outbuf = tmpbuf;
    else
      outbuf = dst;

    /* convert channels */
    ctx->channel_mix (ctx, src, outbuf, samples);

    src = outbuf;
  }

  /* we only need to quantize if output format is int */
  if (ctx->out.is_int) {
    if (ctx->out_default)
      outbuf = dst;
    else
      outbuf = tmpbuf;
    ctx->quantize (ctx, src, outbuf, samples);
  }

  if (!ctx->out_default) {
    /* pack default format into dst */
    ctx->pack (src, dst, ctx->out_scale, samples * ctx->out.channels);
  }

  return TRUE;
}
Ejemplo n.º 6
0
gboolean
audio_convert_prepare_context (AudioConvertCtx * ctx, AudioConvertFmt * in,
    AudioConvertFmt * out, GstAudioConvertDithering dither,
    GstAudioConvertNoiseShaping ns)
{
  gint idx_in, idx_out;

  g_return_val_if_fail (ctx != NULL, FALSE);
  g_return_val_if_fail (in != NULL, FALSE);
  g_return_val_if_fail (out != NULL, FALSE);

  /* first clean the existing context */
  audio_convert_clean_context (ctx);

  g_return_val_if_fail (in->unpositioned_layout == out->unpositioned_layout,
      FALSE);

  ctx->in = *in;
  ctx->out = *out;

  /* Don't dither or apply noise shaping if target depth is bigger than 20 bits
   * as DA converters only can do a SNR up to 20 bits in reality.
   * Also don't dither or apply noise shaping if target depth is larger than
   * source depth. */
  if (ctx->out.depth <= 20 && (!ctx->in.is_int
          || ctx->in.depth >= ctx->out.depth)) {
    ctx->dither = dither;
    ctx->ns = ns;
  } else {
    ctx->dither = DITHER_NONE;
    ctx->ns = NOISE_SHAPING_NONE;
  }

  /* Use simple error feedback when output sample rate is smaller than
   * 32000 as the other methods might move the noise to audible ranges */
  if (ctx->ns > NOISE_SHAPING_ERROR_FEEDBACK && ctx->out.rate < 32000)
    ctx->ns = NOISE_SHAPING_ERROR_FEEDBACK;

  gst_channel_mix_setup_matrix (ctx);

  idx_in = audio_convert_get_func_index (ctx, in);
  ctx->unpack = unpack_funcs[idx_in];

  idx_out = audio_convert_get_func_index (ctx, out);
  ctx->pack = pack_funcs[idx_out];

  /* if both formats are float/double or we use noise shaping use double as
   * intermediate format and and switch mixing */
  if (!DOUBLE_INTERMEDIATE_FORMAT (ctx)) {
    GST_INFO ("use int mixing");
    ctx->channel_mix = (AudioConvertMix) gst_channel_mix_mix_int;
  } else {
    GST_INFO ("use float mixing");
    ctx->channel_mix = (AudioConvertMix) gst_channel_mix_mix_float;
  }
  GST_INFO ("unitsizes: %d -> %d", in->unit_size, out->unit_size);

  /* check if input is in default format */
  ctx->in_default = check_default (ctx, in);
  /* check if channel mixer is passthrough */
  ctx->mix_passthrough = gst_channel_mix_passthrough (ctx);
  /* check if output is in default format */
  ctx->out_default = check_default (ctx, out);

  GST_INFO ("in default %d, mix passthrough %d, out default %d",
      ctx->in_default, ctx->mix_passthrough, ctx->out_default);

  ctx->in_scale = (in->is_int) ? (32 - in->depth) : 0;
  ctx->out_scale = (out->is_int) ? (32 - out->depth) : 0;

  gst_audio_quantize_setup (ctx);

  return TRUE;
}
Ejemplo n.º 7
0
gboolean
audio_convert_prepare_context (AudioConvertCtx * ctx, GstAudioInfo * in,
    GstAudioInfo * out, GstAudioConvertDithering dither,
    GstAudioConvertNoiseShaping ns)
{
  gint idx_in, idx_out;
  gint in_depth, out_depth;

  g_return_val_if_fail (ctx != NULL, FALSE);
  g_return_val_if_fail (in != NULL, FALSE);
  g_return_val_if_fail (out != NULL, FALSE);

  /* first clean the existing context */
  audio_convert_clean_context (ctx);
  if ((GST_AUDIO_INFO_CHANNELS (in) != GST_AUDIO_INFO_CHANNELS (out)) &&
      (GST_AUDIO_INFO_IS_UNPOSITIONED (in)
          || GST_AUDIO_INFO_IS_UNPOSITIONED (out)))
    goto unpositioned;

  ctx->in = *in;
  ctx->out = *out;

  in_depth = GST_AUDIO_FORMAT_INFO_DEPTH (in->finfo);
  out_depth = GST_AUDIO_FORMAT_INFO_DEPTH (out->finfo);

  GST_INFO ("depth in %d, out %d", in_depth, out_depth);

  /* Don't dither or apply noise shaping if target depth is bigger than 20 bits
   * as DA converters only can do a SNR up to 20 bits in reality.
   * Also don't dither or apply noise shaping if target depth is larger than
   * source depth. */
  if (out_depth <= 20 && (!GST_AUDIO_FORMAT_INFO_IS_INTEGER (in->finfo)
          || in_depth >= out_depth)) {
    ctx->dither = dither;
    ctx->ns = ns;
    GST_INFO ("using dither %d and noise shaping %d", dither, ns);
  } else {
    ctx->dither = DITHER_NONE;
    ctx->ns = NOISE_SHAPING_NONE;
    GST_INFO ("using no dither and noise shaping");
  }

  /* Use simple error feedback when output sample rate is smaller than
   * 32000 as the other methods might move the noise to audible ranges */
  if (ctx->ns > NOISE_SHAPING_ERROR_FEEDBACK && out->rate < 32000)
    ctx->ns = NOISE_SHAPING_ERROR_FEEDBACK;

  gst_channel_mix_setup_matrix (ctx);

  idx_in = audio_convert_get_func_index (ctx, in->finfo);
  ctx->unpack = unpack_funcs[idx_in];

  idx_out = audio_convert_get_func_index (ctx, out->finfo);
  ctx->pack = pack_funcs[idx_out];

  GST_INFO ("func index in %d, out %d", idx_in, idx_out);

  /* if both formats are float/double or we use noise shaping use double as
   * intermediate format and switch mixing */
  if (!DOUBLE_INTERMEDIATE_FORMAT (ctx)) {
    GST_INFO ("use int mixing");
    ctx->channel_mix = (AudioConvertMix) gst_channel_mix_mix_int;
  } else {
    GST_INFO ("use float mixing");
    ctx->channel_mix = (AudioConvertMix) gst_channel_mix_mix_float;
  }
  GST_INFO ("unitsizes: %d -> %d", in->bpf, out->bpf);

  /* check if input is in default format */
  ctx->in_default = check_default (ctx, in->finfo);
  /* check if channel mixer is passthrough */
  ctx->mix_passthrough = gst_channel_mix_passthrough (ctx);
  /* check if output is in default format */
  ctx->out_default = check_default (ctx, out->finfo);

  GST_INFO ("in default %d, mix passthrough %d, out default %d",
      ctx->in_default, ctx->mix_passthrough, ctx->out_default);

  ctx->in_scale =
      GST_AUDIO_FORMAT_INFO_IS_INTEGER (in->finfo) ? (32 - in_depth) : 0;
  ctx->out_scale =
      GST_AUDIO_FORMAT_INFO_IS_INTEGER (out->finfo) ? (32 - out_depth) : 0;

  GST_INFO ("scale in %d, out %d", ctx->in_scale, ctx->out_scale);

  gst_audio_quantize_setup (ctx);

  return TRUE;

  /* ERRORS */
unpositioned:
  {
    GST_WARNING ("unpositioned channels");
    return FALSE;
  }
}