Esempio n. 1
0
/**
 * gst_audio_format_build_integer:
 * @sign: signed or unsigned format
 * @endianness: G_LITTLE_ENDIAN or G_BIG_ENDIAN
 * @width: amount of bits used per sample
 * @depth: amount of used bits in @width
 *
 * Construct a #GstAudioFormat with given parameters.
 *
 * Returns: a #GstAudioFormat or GST_AUDIO_FORMAT_UNKNOWN when no audio format
 * exists with the given parameters.
 */
GstAudioFormat
gst_audio_format_build_integer (gboolean sign, gint endianness,
    gint width, gint depth)
{
  gint i, e;

  for (i = 0; i < G_N_ELEMENTS (formats); i++) {
    GstAudioFormatInfo *finfo = &formats[i];

    /* must be int */
    if (!GST_AUDIO_FORMAT_INFO_IS_INTEGER (finfo))
      continue;

    /* width and depth must match */
    if (width != GST_AUDIO_FORMAT_INFO_WIDTH (finfo))
      continue;
    if (depth != GST_AUDIO_FORMAT_INFO_DEPTH (finfo))
      continue;

    /* if there is endianness, it must match */
    e = GST_AUDIO_FORMAT_INFO_ENDIANNESS (finfo);
    if (e && e != endianness)
      continue;

    /* check sign */
    if ((sign && !GST_AUDIO_FORMAT_INFO_IS_SIGNED (finfo)) ||
        (!sign && GST_AUDIO_FORMAT_INFO_IS_SIGNED (finfo)))
      continue;

    return GST_AUDIO_FORMAT_INFO_FORMAT (finfo);
  }
  return GST_AUDIO_FORMAT_UNKNOWN;
}
Esempio n. 2
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;
}
Esempio n. 3
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;
  gint in_width, out_width;

  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.bpf * samples;
  outsize = ctx->out.bpf * samples;

  in_width = GST_AUDIO_FORMAT_INFO_WIDTH (ctx->in.finfo);
  out_width = GST_AUDIO_FORMAT_INFO_WIDTH (ctx->out.finfo);

  /* 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, in_width);
  if (!ctx->mix_passthrough || !ctx->out_default)
    outtemp = gst_util_uint64_scale (outsize, size * 8, out_width);
  biggest = MAX (intemp, outtemp);

  /* see if one of the buffers can be used as temp */
  if ((outsize >= biggest) && (ctx->out.bpf <= size))
    tmpbuf = dst;
  else if ((insize >= biggest) && src_writable && (ctx->in.bpf >= 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 (GST_AUDIO_FORMAT_INFO_IS_INTEGER (ctx->out.finfo)) {
    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;
}
Esempio n. 4
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;
  }
}