コード例 #1
0
ファイル: sound_io.c プロジェクト: andrew-taylor/Bowerbird
void
soundfile_write_double(soundfile_t *sf, double *buffer, index_t n_frames) {
	if (sf->t == sft_libsndfile) {
		sf_count_t count; 
		if ((count = sf_writef_double(sf->p, buffer, n_frames)) != n_frames)
			sdie(sf->p, "sf_writef_double returned %d (expected %d): ", count, n_frames);
	} else {
		WavpackContext *wpc = sf->p;
		int32_t sample_buffer[n_frames*sf->channels];
		for (int i = 0; i < 10; i++)
			dp(30, "buffer[%d]=%g\n", i, (double)buffer[i]);
		
		double multiplier = 1L << (sf->bits_per_sample - 1);
		for (int i = 0; i < n_frames*sf->channels; i++)
  	  		sample_buffer[i] = multiplier*buffer[i]; // FIXME may overflow buffer[1] == 1
		if (!WavpackPackSamples(sf->p, sample_buffer, n_frames))
            die("WavpackPackSamples failed: %s\n", WavpackGetErrorMessage(wpc));
	}
}
コード例 #2
0
static GstFlowReturn
gst_wavpack_enc_chain (GstPad * pad, GstBuffer * buf)
{
  GstWavpackEnc *enc = GST_WAVPACK_ENC (gst_pad_get_parent (pad));
  uint32_t sample_count = GST_BUFFER_SIZE (buf) / 4;
  GstFlowReturn ret;

  /* reset the last returns to GST_FLOW_OK. This is only set to something else
   * while WavpackPackSamples() or more specific gst_wavpack_enc_push_block()
   * so not valid anymore */
  enc->srcpad_last_return = enc->wvcsrcpad_last_return = GST_FLOW_OK;

  GST_DEBUG ("got %u raw samples", sample_count);

  /* check if we already have a valid WavpackContext, otherwise make one */
  if (!enc->wp_context) {
    /* create raw context */
    enc->wp_context =
        WavpackOpenFileOutput (gst_wavpack_enc_push_block, &enc->wv_id,
        (enc->correction_mode > 0) ? &enc->wvc_id : NULL);
    if (!enc->wp_context) {
      GST_ELEMENT_ERROR (enc, LIBRARY, INIT, (NULL),
          ("error creating Wavpack context"));
      gst_object_unref (enc);
      gst_buffer_unref (buf);
      return GST_FLOW_ERROR;
    }

    /* set the WavpackConfig according to our parameters */
    gst_wavpack_enc_set_wp_config (enc);

    /* set the configuration to the context now that we know everything
     * and initialize the encoder */
    if (!WavpackSetConfiguration (enc->wp_context,
            enc->wp_config, (uint32_t) (-1))
        || !WavpackPackInit (enc->wp_context)) {
      GST_ELEMENT_ERROR (enc, LIBRARY, SETTINGS, (NULL),
          ("error setting up wavpack encoding context"));
      WavpackCloseFile (enc->wp_context);
      gst_object_unref (enc);
      gst_buffer_unref (buf);
      return GST_FLOW_ERROR;
    }
    GST_DEBUG ("setup of encoding context successfull");
  }

  /* Save the timestamp of the first buffer. This will be later
   * used as offset for all following buffers */
  if (enc->timestamp_offset == GST_CLOCK_TIME_NONE) {
    if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
      enc->timestamp_offset = GST_BUFFER_TIMESTAMP (buf);
      enc->next_ts = GST_BUFFER_TIMESTAMP (buf);
    } else {
      enc->timestamp_offset = 0;
      enc->next_ts = 0;
    }
  }

  /* Check if we have a continous stream, if not drop some samples or the buffer or
   * insert some silence samples */
  if (enc->next_ts != GST_CLOCK_TIME_NONE &&
      GST_BUFFER_TIMESTAMP (buf) < enc->next_ts) {
    guint64 diff = enc->next_ts - GST_BUFFER_TIMESTAMP (buf);
    guint64 diff_bytes;

    GST_WARNING_OBJECT (enc, "Buffer is older than previous "
        "timestamp + duration (%" GST_TIME_FORMAT "< %" GST_TIME_FORMAT
        "), cannot handle. Clipping buffer.",
        GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
        GST_TIME_ARGS (enc->next_ts));

    diff_bytes =
        GST_CLOCK_TIME_TO_FRAMES (diff, enc->samplerate) * enc->channels * 2;
    if (diff_bytes >= GST_BUFFER_SIZE (buf)) {
      gst_buffer_unref (buf);
      return GST_FLOW_OK;
    }
    buf = gst_buffer_make_metadata_writable (buf);
    GST_BUFFER_DATA (buf) += diff_bytes;
    GST_BUFFER_SIZE (buf) -= diff_bytes;

    GST_BUFFER_TIMESTAMP (buf) += diff;
    if (GST_BUFFER_DURATION_IS_VALID (buf))
      GST_BUFFER_DURATION (buf) -= diff;
  }

  /* Allow a diff of at most 5 ms */
  if (enc->next_ts != GST_CLOCK_TIME_NONE
      && GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
    if (GST_BUFFER_TIMESTAMP (buf) != enc->next_ts &&
        GST_BUFFER_TIMESTAMP (buf) - enc->next_ts > 5 * GST_MSECOND) {
      GST_WARNING_OBJECT (enc,
          "Discontinuity detected: %" G_GUINT64_FORMAT " > %" G_GUINT64_FORMAT,
          GST_BUFFER_TIMESTAMP (buf) - enc->next_ts, 5 * GST_MSECOND);

      WavpackFlushSamples (enc->wp_context);
      enc->timestamp_offset += (GST_BUFFER_TIMESTAMP (buf) - enc->next_ts);
    }
  }

  if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)
      && GST_BUFFER_DURATION_IS_VALID (buf))
    enc->next_ts = GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf);
  else
    enc->next_ts = GST_CLOCK_TIME_NONE;

  if (enc->need_channel_remap) {
    buf = gst_buffer_make_writable (buf);
    gst_wavpack_enc_fix_channel_order (enc, (gint32 *) GST_BUFFER_DATA (buf),
        sample_count);
  }

  /* if we want to append the MD5 sum to the stream update it here
   * with the current raw samples */
  if (enc->md5) {
    g_checksum_update (enc->md5_context, GST_BUFFER_DATA (buf),
        GST_BUFFER_SIZE (buf));
  }

  /* encode and handle return values from encoding */
  if (WavpackPackSamples (enc->wp_context, (int32_t *) GST_BUFFER_DATA (buf),
          sample_count / enc->channels)) {
    GST_DEBUG ("encoding samples successful");
    ret = GST_FLOW_OK;
  } else {
    if ((enc->srcpad_last_return == GST_FLOW_RESEND) ||
        (enc->wvcsrcpad_last_return == GST_FLOW_RESEND)) {
      ret = GST_FLOW_RESEND;
    } else if ((enc->srcpad_last_return == GST_FLOW_OK) ||
        (enc->wvcsrcpad_last_return == GST_FLOW_OK)) {
      ret = GST_FLOW_OK;
    } else if ((enc->srcpad_last_return == GST_FLOW_NOT_LINKED) &&
        (enc->wvcsrcpad_last_return == GST_FLOW_NOT_LINKED)) {
      ret = GST_FLOW_NOT_LINKED;
    } else if ((enc->srcpad_last_return == GST_FLOW_WRONG_STATE) &&
        (enc->wvcsrcpad_last_return == GST_FLOW_WRONG_STATE)) {
      ret = GST_FLOW_WRONG_STATE;
    } else {
      GST_ELEMENT_ERROR (enc, LIBRARY, ENCODE, (NULL),
          ("encoding samples failed"));
      ret = GST_FLOW_ERROR;
    }
  }

  gst_buffer_unref (buf);
  gst_object_unref (enc);
  return ret;
}
コード例 #3
0
ファイル: wav2wv.c プロジェクト: BackupTheBerlios/bimmerbox
static int wav2wv (char *filename)
{
    int in_fd, out_fd, num_chans, error = false, last_buttons;
    unsigned long total_bytes_read = 0, total_bytes_written = 0;
    unsigned long total_samples, samples_remaining;
    long *input_buffer = (long *) audiobuf;
    unsigned char *output_buffer = audiobuf + 0x100000;
    char *extension, save_a;
    WavpackConfig config;
    WavpackContext *wpc;
    long start_tick;

    rb->lcd_clear_display();
    rb->lcd_puts_scroll(0, 0, filename);
#ifdef HAVE_LCD_BITMAP
    rb->lcd_update();
#endif

    last_buttons = rb->button_status ();
    start_tick = *rb->current_tick;
    extension = filename + rb->strlen (filename) - 3;

    if (rb->strcasecmp (extension, "wav")) {
        rb->splash(HZ*2, true, "only for wav files!");
        return 1;
    }

    in_fd = rb->open(filename, O_RDONLY);

    if (in_fd < 0) {
        rb->splash(HZ*2, true, "could not open file!");
        return true;
    }

    if (rb->read (in_fd, &raw_header, sizeof (raw_header)) != sizeof (raw_header)) {
        rb->splash(HZ*2, true, "could not read file!");
        return true;
    }

    total_bytes_read += sizeof (raw_header);
    rb->memcpy (&native_header, &raw_header, sizeof (raw_header));
    little_endian_to_native (&native_header, WAV_HEADER_FORMAT);

	if (rb->strncmp (native_header.ckID, "RIFF", 4) ||
	    rb->strncmp (native_header.fmt_ckID, "fmt ", 4) ||
	    rb->strncmp (native_header.data_ckID, "data", 4) ||
        native_header.FormatTag != 1 || native_header.BitsPerSample != 16) {
            rb->splash(HZ*2, true, "incompatible wav file!");
            return true;
    }

    wpc = WavpackOpenFileOutput ();

    rb->memset (&config, 0, sizeof (config));
    config.bits_per_sample = 16;
    config.bytes_per_sample = 2;
    config.sample_rate = native_header.SampleRate;
    num_chans = config.num_channels = native_header.NumChannels;
	total_samples = native_header.data_ckSize / native_header.BlockAlign;

//  config.flags |= CONFIG_HIGH_FLAG;

    if (!WavpackSetConfiguration (wpc, &config, total_samples)) {
        rb->splash(HZ*2, true, "internal error!");
        rb->close (in_fd);
        return true;
    }

    WavpackAddWrapper (wpc, &raw_header, sizeof (raw_header));
    save_a = extension [1];
    extension [1] = extension [2];
    extension [2] = 0;

    out_fd = rb->creat (filename, O_WRONLY);

    extension [2] = extension [1];
    extension [1] = save_a;

    if (out_fd < 0) {
        rb->splash(HZ*2, true, "could not create file!");
        rb->close (in_fd);
        return true;
    }

    wvupdate (start_tick, native_header.SampleRate, total_samples, 0, 0, 0);

    for (samples_remaining = total_samples; samples_remaining;) {
        unsigned long samples_count, samples_to_pack, bytes_count;
        int cnt, buttons;
        long value, *lp;
        char *cp;
 
        samples_count = SAMPLES_PER_BLOCK;

        if (samples_count > samples_remaining)
            samples_count = samples_remaining;

        bytes_count = samples_count * num_chans * 2;

        if (rb->read (in_fd, input_buffer, bytes_count) != (long) bytes_count) {
            rb->splash(HZ*2, true, "could not read file!");
            error = true;
            break;
        }

        total_bytes_read += bytes_count;
        WavpackStartBlock (wpc, output_buffer, output_buffer + 0x100000);
        samples_to_pack = samples_count;
        cp = (char *) input_buffer;

        while (samples_to_pack) {
            unsigned long samples_this_pass = TEMP_SAMPLES / num_chans;

            if (samples_this_pass > samples_to_pack)
                samples_this_pass = samples_to_pack;

            lp = temp_buffer;
            cnt = samples_this_pass;

            if (num_chans == 2)
                while (cnt--) {
                    value = *cp++ & 0xff;
                    value += *cp++ << 8;
                    *lp++ = value;
                    value = *cp++ & 0xff;
                    value += *cp++ << 8;
                    *lp++ = value;
                } 
            else
                while (cnt--) {
                    value = *cp++ & 0xff;
                    value += *cp++ << 8;
                    *lp++ = value;
                } 

            if (!WavpackPackSamples (wpc, temp_buffer, samples_this_pass)) {
                rb->splash(HZ*2, true, "internal error!");
                error = true;
                break;
            }

            samples_to_pack -= samples_this_pass;
        }

        if (error)
            break;

        bytes_count = WavpackFinishBlock (wpc);

        if (rb->write (out_fd, output_buffer, bytes_count) != (long) bytes_count) {
            rb->splash(HZ*2, true, "could not write file!");
            error = true;
            break;
        }

        total_bytes_written += bytes_count;
        samples_remaining -= samples_count;

        wvupdate (start_tick, native_header.SampleRate, total_samples,
            total_samples - samples_remaining, total_bytes_read, total_bytes_written);

        buttons = rb->button_status ();

        if (last_buttons == BUTTON_NONE && buttons != BUTTON_NONE) {
            rb->splash(HZ*2, true, "operation aborted!");
            error = true;
            break;
        }
        else
            last_buttons = buttons;
    }

    rb->close (out_fd);
    rb->close (in_fd);

    if (error) {
        save_a = extension [1];
        extension [1] = extension [2];
        extension [2] = 0;
        rb->remove (filename);
        extension [2] = extension [1];
        extension [1] = save_a;
    }
    else
        rb->splash(HZ*3, true, "operation successful");

    return error;
}
コード例 #4
0
static GstFlowReturn
gst_wavpack_enc_chain (GstPad * pad, GstBuffer * buf)
{
  GstWavpackEnc *enc = GST_WAVPACK_ENC (gst_pad_get_parent (pad));
  uint32_t sample_count = GST_BUFFER_SIZE (buf) / 4;
  GstFlowReturn ret;

  /* reset the last returns to GST_FLOW_OK. This is only set to something else
   * while WavpackPackSamples() or more specific gst_wavpack_enc_push_block()
   * so not valid anymore */
  enc->srcpad_last_return = enc->wvcsrcpad_last_return = GST_FLOW_OK;

  GST_DEBUG ("got %u raw samples", sample_count);

  /* check if we already have a valid WavpackContext, otherwise make one */
  if (!enc->wp_context) {
    /* create raw context */
    enc->wp_context =
        WavpackOpenFileOutput (gst_wavpack_enc_push_block, &enc->wv_id,
        (enc->correction_mode > 0) ? &enc->wvc_id : NULL);
    if (!enc->wp_context) {
      GST_ELEMENT_ERROR (enc, LIBRARY, INIT, (NULL),
          ("error creating Wavpack context"));
      gst_object_unref (enc);
      gst_buffer_unref (buf);
      return GST_FLOW_ERROR;
    }

    /* set the WavpackConfig according to our parameters */
    gst_wavpack_enc_set_wp_config (enc);

    /* set the configuration to the context now that we know everything
     * and initialize the encoder */
    if (!WavpackSetConfiguration (enc->wp_context,
            enc->wp_config, (uint32_t) (-1))
        || !WavpackPackInit (enc->wp_context)) {
      GST_ELEMENT_ERROR (enc, LIBRARY, SETTINGS, (NULL),
          ("error setting up wavpack encoding context"));
      WavpackCloseFile (enc->wp_context);
      gst_object_unref (enc);
      gst_buffer_unref (buf);
      return GST_FLOW_ERROR;
    }
    GST_DEBUG ("setup of encoding context successfull");
  }

  if (enc->need_channel_remap) {
    buf = gst_buffer_make_writable (buf);
    gst_wavpack_enc_fix_channel_order (enc, (gint32 *) GST_BUFFER_DATA (buf),
        sample_count);
  }

  /* if we want to append the MD5 sum to the stream update it here
   * with the current raw samples */
  if (enc->md5) {
    MD5Update (enc->md5_context, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
  }

  /* encode and handle return values from encoding */
  if (WavpackPackSamples (enc->wp_context, (int32_t *) GST_BUFFER_DATA (buf),
          sample_count / enc->channels)) {
    GST_DEBUG ("encoding samples successful");
    ret = GST_FLOW_OK;
  } else {
    if ((enc->srcpad_last_return == GST_FLOW_RESEND) ||
        (enc->wvcsrcpad_last_return == GST_FLOW_RESEND)) {
      ret = GST_FLOW_RESEND;
    } else if ((enc->srcpad_last_return == GST_FLOW_OK) ||
        (enc->wvcsrcpad_last_return == GST_FLOW_OK)) {
      ret = GST_FLOW_OK;
    } else if ((enc->srcpad_last_return == GST_FLOW_NOT_LINKED) &&
        (enc->wvcsrcpad_last_return == GST_FLOW_NOT_LINKED)) {
      ret = GST_FLOW_NOT_LINKED;
    } else if ((enc->srcpad_last_return == GST_FLOW_WRONG_STATE) &&
        (enc->wvcsrcpad_last_return == GST_FLOW_WRONG_STATE)) {
      ret = GST_FLOW_WRONG_STATE;
    } else {
      GST_ELEMENT_ERROR (enc, LIBRARY, ENCODE, (NULL),
          ("encoding samples failed"));
      ret = GST_FLOW_ERROR;
    }
  }

  gst_buffer_unref (buf);
  gst_object_unref (enc);
  return ret;
}