void wavpack_buffer_format_samples(wavpack_buffer_decoder* wbd,
                                   uchar *dst, long *src, uint32_t samples)
{
    long temp;
    int bps = WavpackGetBytesPerSample(wbd->wpc);
    uint32_t samcnt = samples * WavpackGetNumChannels (wbd->wpc);

    switch (bps) {
        
    case 1:
        while (samcnt--)
            *dst++ = (uchar)(*src++ + 128);
        
        break;
        
    case 2:
        while (samcnt--) {
            *dst++ = (uchar)(temp = *src++);
            *dst++ = (uchar)(temp >> 8);
        }
        
        break;
        
    case 3:
        while (samcnt--) {
            *dst++ = (uchar)(temp = *src++);
            *dst++ = (uchar)(temp >> 8);
            *dst++ = (uchar)(temp >> 16);
        }
        
        break;
    }
}
Esempio n. 2
0
soundfile_t *
soundfile_open_read(const char *path) {
	dp(30, "path=%s \n", path);
	soundfile_t *s = salloc(sizeof *s);
	s->m = sft_read;
	if 	(g_regex_match_simple ("\\.wv$", path, 0, 0)) {
		char error[80] = {0};
	    int flags = 0;
	    int norm_offset = 0;
		s->t = sft_wavpack;
	    s->p = WavpackOpenFileInput(path, error, flags, norm_offset);
		if (!s->p)
			die("can not open input file '%s'", path);
		s->bits_per_sample = WavpackGetBitsPerSample(s->p);
		s->channels = WavpackGetNumChannels(s->p);
		s->samplerate = WavpackGetSampleRate(s->p);
		s->frames = WavpackGetNumSamples(s->p);
	} else {
		SF_INFO	 	infile_info = {0};
		if (strcmp(path, "-"))
			s->p = sf_open(path, SFM_READ, &infile_info);
		else
			s->p = sf_open_fd(0, SFM_READ, &infile_info, 0);
		if (!s->p)
			die("can not open input file '%s'", path);
		s->t = sft_libsndfile;
		s->channels = infile_info.channels;
		s->samplerate = infile_info.samplerate;
		s->frames = infile_info.frames;
	}
	return s;
}
Esempio n. 3
0
static void
wv_get_song_info(char *filename, char **title, int *length)
{
    assert(filename != NULL);
    char error_buff[80];
    WavpackContext *ctx = WavpackOpenFileInput(filename, error_buff, OPEN_TAGS | OPEN_WVC, 0);
    if (ctx == NULL) {
        printf("wavpack: Error opening file: \"%s: %s\"\n", filename, error_buff);
        return;
    }
    int sample_rate = WavpackGetSampleRate(ctx);
    int num_channels = WavpackGetNumChannels(ctx);
    DBG("reading %s at %d rate with %d channels\n", filename, sample_rate, num_channels);

    *length = (int)(WavpackGetNumSamples(ctx) / sample_rate) * 1000,
     *title = generate_title(filename, ctx);
    DBG("title for %s = %s\n", filename, *title);
    WavpackCloseFile(ctx);
}
void wavpack_buffer_format_samples(wavpack_buffer_decoder* wbd,
                                   uchar *dst, long *src, uint32_t samples, int float32_output)
{
    long temp;
    int bps = WavpackGetBytesPerSample(wbd->wpc);
    uint32_t samcnt = samples * WavpackGetNumChannels (wbd->wpc);

    switch (bps) {
        
    case 1:
        while (samcnt--)
            *dst++ = (uchar)(*src++ + 128);
        
        break;
        
    case 2:
        while (samcnt--) {
            *dst++ = (uchar)(temp = *src++);
            *dst++ = (uchar)(temp >> 8);
        }
        
        break;
        
    case 3:
        while (samcnt--) {
            *dst++ = (uchar)(temp = *src++);
            *dst++ = (uchar)(temp >> 8);
            *dst++ = (uchar)(temp >> 16);
        }
        
        break;

    case 4:
        if (float32_output && !(WavpackGetMode (wbd->wpc) & MODE_FLOAT)) {
            float *fdst = (float *) dst;

            while (samcnt--)
                *fdst++ = *src++ * 4.656612873077393e-10F;
        }
        break;
    }
}
Esempio n. 5
0
    bool attach(const char *filename)
    {
        ctx = WavpackOpenFileInput(filename, error_buff, OPEN_TAGS | OPEN_WVC | OPEN_NORMALIZE, 0);

        if (ctx == NULL) {
            return false;
        }

        sample_rate = WavpackGetSampleRate(ctx);
        num_channels = WavpackGetNumChannels(ctx);
        bytes_per_sample = WavpackGetBytesPerSample(ctx);
        input = (int32_t *)calloc(BUFFER_SIZE, num_channels * sizeof(int32_t));
        output = (int16_t *)calloc(BUFFER_SIZE, num_channels * sizeof(int16_t));
        memset (shaping_error, 0, sizeof (shaping_error));
        mod->set_info(generate_title(filename, ctx),
                      (int) (WavpackGetNumSamples(ctx) / sample_rate) * 1000,
                      (int) WavpackGetAverageBitrate(ctx, true),
                      (int) sample_rate, num_channels);
        play_gain = calculate_gain (ctx);
        DBG("gain value = %g\n", play_gain);
        return true;
    }
Esempio n. 6
0
gboolean Wavpack_Header_Read_File_Info(gchar *filename, ET_File_Info *ETFileInfo)
{
    WavpackContext *wpc;

    wpc = WavpackOpenFileInput(filename, NULL, 0, 0);

    if ( wpc == NULL ) {
        return FALSE;
    }

    ETFileInfo->version     = WavpackGetVersion(wpc);
    /* .wvc correction file not counted */
    ETFileInfo->bitrate     = WavpackGetAverageBitrate(wpc, 0)/1000;
    ETFileInfo->samplerate  = WavpackGetSampleRate(wpc);
    ETFileInfo->mode        = WavpackGetNumChannels(wpc);
    ETFileInfo->size        = WavpackGetFileSize(wpc);
    ETFileInfo->duration    = WavpackGetNumSamples(wpc)/ETFileInfo->samplerate;

    WavpackCloseFile(wpc);

    return TRUE;
}
Esempio n. 7
0
EmErrorCode WvDecoder::Open(const std::string& url)
{
    m_Ctx = WavpackOpenFileInput(url.c_str(), nullptr, 0, 0);
    if (m_Ctx == nullptr)
        return ErrorCode::DecoderFailedToOpen;

    if (WavpackGetNumSamples(m_Ctx) == (uint32_t) -1)
        return ErrorCode::DecoderFailedToInit;

    m_Duration = (double)WavpackGetNumSamples(m_Ctx) / WavpackGetSampleRate(m_Ctx) * 1000;
    m_Channels = WavpackGetNumChannels(m_Ctx);
    m_SampleRate = WavpackGetSampleRate(m_Ctx);
    m_BitsPerSample = WavpackGetBitsPerSample(m_Ctx);
    m_BytesPerSample = WavpackGetBytesPerSample(m_Ctx);

    // one sample may not be enough to build a full channel
    m_UnitCount = WavpackGetNumSamples(m_Ctx)/m_Channels;
    m_UnitIndex = 0;

    m_Buf.resize(10 * m_Channels * sizeof(int32_t)); // 1~10 full-samples

    return ErrorCode::Ok;
}
Esempio n. 8
0
int CSound::LoadWV(const char *pFilename)
{
	CSample *pSample;
	int SampleID = -1;
	char aError[100];
	WavpackContext *pContext;

	// don't waste memory on sound when we are stress testing
	if(g_Config.m_DbgStress)
		return -1;

	// no need to load sound when we are running with no sound
	if(!m_SoundEnabled)
		return 1;

	if(!m_pStorage)
		return -1;

	ms_File = m_pStorage->OpenFile(pFilename, IOFLAG_READ, IStorage::TYPE_ALL);
	if(!ms_File)
	{
		dbg_msg("sound/wv", "failed to open file. filename='%s'", pFilename);
		return -1;
	}

	SampleID = AllocID();
	if(SampleID < 0)
		return -1;
	pSample = &m_aSamples[SampleID];

	pContext = WavpackOpenFileInput(ReadData, aError);
	if (pContext)
	{
		int m_aSamples = WavpackGetNumSamples(pContext);
		int BitsPerSample = WavpackGetBitsPerSample(pContext);
		unsigned int SampleRate = WavpackGetSampleRate(pContext);
		int m_aChannels = WavpackGetNumChannels(pContext);
		int *pData;
		int *pSrc;
		short *pDst;
		int i;

		pSample->m_Channels = m_aChannels;
		pSample->m_Rate = SampleRate;

		if(pSample->m_Channels > 2)
		{
			dbg_msg("sound/wv", "file is not mono or stereo. filename='%s'", pFilename);
			return -1;
		}

		/*
		if(snd->rate != 44100)
		{
			dbg_msg("sound/wv", "file is %d Hz, not 44100 Hz. filename='%s'", snd->rate, filename);
			return -1;
		}*/

		if(BitsPerSample != 16)
		{
			dbg_msg("sound/wv", "bps is %d, not 16, filname='%s'", BitsPerSample, pFilename);
			return -1;
		}

		pData = (int *)mem_alloc(4*m_aSamples*m_aChannels, 1);
		WavpackUnpackSamples(pContext, pData, m_aSamples); // TODO: check return value
		pSrc = pData;

		pSample->m_pData = (short *)mem_alloc(2*m_aSamples*m_aChannels, 1);
		pDst = pSample->m_pData;

		for (i = 0; i < m_aSamples*m_aChannels; i++)
			*pDst++ = (short)*pSrc++;

		mem_free(pData);

		pSample->m_NumFrames = m_aSamples;
		pSample->m_LoopStart = -1;
		pSample->m_LoopEnd = -1;
		pSample->m_PausedAt = 0;
	}
	else
	{
		dbg_msg("sound/wv", "failed to open %s: %s", pFilename, aError);
	}

	io_close(ms_File);
	ms_File = NULL;

	if(g_Config.m_Debug)
		dbg_msg("sound/wv", "loaded %s", pFilename);

	RateConvert(SampleID);
	return SampleID;
}
Esempio n. 9
0
static GstFlowReturn
gst_wavpack_dec_chain (GstPad * pad, GstBuffer * buf)
{
    GstWavpackDec *dec;
    GstBuffer *outbuf;
    GstFlowReturn ret = GST_FLOW_OK;
    WavpackHeader wph;
    int32_t decoded, unpacked_size;
    gboolean format_changed;

    dec = GST_WAVPACK_DEC (GST_PAD_PARENT (pad));

    /* check input, we only accept framed input with complete chunks */
    if (GST_BUFFER_SIZE (buf) < sizeof (WavpackHeader))
        goto input_not_framed;

    if (!gst_wavpack_read_header (&wph, GST_BUFFER_DATA (buf)))
        goto invalid_header;

    if (GST_BUFFER_SIZE (buf) < wph.ckSize + 4 * 1 + 4)
        goto input_not_framed;

    if (!(wph.flags & INITIAL_BLOCK))
        goto input_not_framed;

    dec->wv_id.buffer = GST_BUFFER_DATA (buf);
    dec->wv_id.length = GST_BUFFER_SIZE (buf);
    dec->wv_id.position = 0;

    /* create a new wavpack context if there is none yet but if there
     * was already one (i.e. caps were set on the srcpad) check whether
     * the new one has the same caps */
    if (!dec->context) {
        gchar error_msg[80];

        dec->context = WavpackOpenFileInputEx (dec->stream_reader,
                                               &dec->wv_id, NULL, error_msg, OPEN_STREAMING, 0);

        if (!dec->context) {
            GST_WARNING ("Couldn't decode buffer: %s", error_msg);
            dec->error_count++;
            if (dec->error_count <= WAVPACK_DEC_MAX_ERRORS) {
                goto out;               /* just return OK for now */
            } else {
                goto decode_error;
            }
        }
    }

    g_assert (dec->context != NULL);

    dec->error_count = 0;

    format_changed =
        (dec->sample_rate != WavpackGetSampleRate (dec->context)) ||
        (dec->channels != WavpackGetNumChannels (dec->context)) ||
        (dec->depth != WavpackGetBitsPerSample (dec->context)) ||
#ifdef WAVPACK_OLD_API
        (dec->channel_mask != dec->context->config.channel_mask);
#else
        (dec->channel_mask != WavpackGetChannelMask (dec->context));
#endif

    if (!GST_PAD_CAPS (dec->srcpad) || format_changed) {
        GstCaps *caps;
        gint channel_mask;

        dec->sample_rate = WavpackGetSampleRate (dec->context);
        dec->channels = WavpackGetNumChannels (dec->context);
        dec->depth = WavpackGetBitsPerSample (dec->context);

        caps = gst_caps_new_simple ("audio/x-raw-int",
                                    "rate", G_TYPE_INT, dec->sample_rate,
                                    "channels", G_TYPE_INT, dec->channels,
                                    "depth", G_TYPE_INT, dec->depth,
                                    "width", G_TYPE_INT, 32,
                                    "endianness", G_TYPE_INT, G_BYTE_ORDER,
                                    "signed", G_TYPE_BOOLEAN, TRUE, NULL);

#ifdef WAVPACK_OLD_API
        channel_mask = dec->context->config.channel_mask;
#else
        channel_mask = WavpackGetChannelMask (dec->context);
#endif
        if (channel_mask == 0)
            channel_mask = gst_wavpack_get_default_channel_mask (dec->channels);

        dec->channel_mask = channel_mask;

        /* Only set the channel layout for more than two channels
         * otherwise things break unfortunately */
        if (channel_mask != 0 && dec->channels > 2)
            if (!gst_wavpack_set_channel_layout (caps, channel_mask))
                GST_WARNING_OBJECT (dec, "Failed to set channel layout");

        GST_DEBUG_OBJECT (dec, "setting caps %" GST_PTR_FORMAT, caps);

        /* should always succeed */
        gst_pad_set_caps (dec->srcpad, caps);
        gst_caps_unref (caps);

        /* send GST_TAG_AUDIO_CODEC and GST_TAG_BITRATE tags before something
         * is decoded or after the format has changed */
        gst_wavpack_dec_post_tags (dec);
    }

    /* alloc output buffer */
    unpacked_size = 4 * wph.block_samples * dec->channels;
    ret = gst_pad_alloc_buffer (dec->srcpad, GST_BUFFER_OFFSET (buf),
                                unpacked_size, GST_PAD_CAPS (dec->srcpad), &outbuf);

    if (ret != GST_FLOW_OK)
        goto out;

    gst_buffer_copy_metadata (outbuf, buf, GST_BUFFER_COPY_TIMESTAMPS);

    /* If we got a DISCONT buffer forward the flag. Nothing else
     * has to be done as libwavpack doesn't store state between
     * Wavpack blocks */
    if (GST_BUFFER_IS_DISCONT (buf) || dec->next_block_index != wph.block_index)
        GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);

    dec->next_block_index = wph.block_index + wph.block_samples;

    /* decode */
    decoded = WavpackUnpackSamples (dec->context,
                                    (int32_t *) GST_BUFFER_DATA (outbuf), wph.block_samples);
    if (decoded != wph.block_samples)
        goto decode_error;

    if ((outbuf = gst_audio_buffer_clip (outbuf, &dec->segment,
                                         dec->sample_rate, 4 * dec->channels))) {
        GST_LOG_OBJECT (dec, "pushing buffer with time %" GST_TIME_FORMAT,
                        GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)));
        ret = gst_pad_push (dec->srcpad, outbuf);
    }

out:

    if (G_UNLIKELY (ret != GST_FLOW_OK)) {
        GST_DEBUG_OBJECT (dec, "flow: %s", gst_flow_get_name (ret));
    }

    gst_buffer_unref (buf);

    return ret;

    /* ERRORS */
input_not_framed:
    {
        GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), ("Expected framed input"));
        gst_buffer_unref (buf);
        return GST_FLOW_ERROR;
    }
invalid_header:
    {
        GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), ("Invalid wavpack header"));
        gst_buffer_unref (buf);
        return GST_FLOW_ERROR;
    }
decode_error:
    {
        const gchar *reason = "unknown";

        if (dec->context) {
#ifdef WAVPACK_OLD_API
            reason = dec->context->error_message;
#else
            reason = WavpackGetErrorMessage (dec->context);
#endif
        } else {
            reason = "couldn't create decoder context";
        }
        GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL),
                           ("Failed to decode wavpack stream: %s", reason));
        gst_buffer_unref (outbuf);
        gst_buffer_unref (buf);
        return GST_FLOW_ERROR;
    }
}
Esempio n. 10
0
static DB_playItem_t *
wv_insert (ddb_playlist_t *plt, DB_playItem_t *after, const char *fname) {
    DB_FILE *fp = deadbeef->fopen (fname);
    if (!fp) {
        return NULL;
    }
    char error[80];
#ifdef TINYWV
    WavpackContext *ctx = WavpackOpenFileInput (wv_read_stream, fp, error);
#else
    WavpackContext *ctx = WavpackOpenFileInputEx (&wsr, fp, NULL, error, 0, 0);
#endif
    if (!ctx) {
        fprintf (stderr, "wavpack error: %s\n", error);
        deadbeef->fclose (fp);
        return NULL;
    }
    int totalsamples = WavpackGetNumSamples (ctx);
    int samplerate = WavpackGetSampleRate (ctx);
    float duration = (float)totalsamples / samplerate;

    DB_playItem_t *it = deadbeef->pl_item_alloc_init (fname, plugin.plugin.id);
    deadbeef->pl_add_meta (it, ":FILETYPE", "wv");
    deadbeef->plt_set_item_duration (plt, it, duration);
    trace ("wv: totalsamples=%d, samplerate=%d, duration=%f\n", totalsamples, samplerate, duration);

#if 0
    int num = WavpackGetNumTagItems (ctx);
    trace ("num tag items: %d\n", num);

    for (int i = 0; i < num; i++) {
        char str[1024];
        WavpackGetTagItemIndexed (ctx, i, str, sizeof (str));
        trace ("tag item: %s\n", str);
    }

#endif
    int apeerr = deadbeef->junk_apev2_read (it, fp);
    if (!apeerr) {
        trace ("wv: ape tag found\n");
    }
    int v1err = deadbeef->junk_id3v1_read (it, fp);
    if (!v1err) {
        trace ("wv: id3v1 tag found\n");
    }
    deadbeef->pl_add_meta (it, "title", NULL);

    char s[100];
    snprintf (s, sizeof (s), "%lld", deadbeef->fgetlength (fp));
    deadbeef->pl_add_meta (it, ":FILE_SIZE", s);
    snprintf (s, sizeof (s), "%d", WavpackGetBytesPerSample (ctx) * 8);
    deadbeef->pl_add_meta (it, ":BPS", s);
    snprintf (s, sizeof (s), "%d", WavpackGetNumChannels (ctx));
    deadbeef->pl_add_meta (it, ":CHANNELS", s);
    snprintf (s, sizeof (s), "%d", WavpackGetSampleRate (ctx));
    deadbeef->pl_add_meta (it, ":SAMPLERATE", s);
    snprintf (s, sizeof (s), "%d", (int)(WavpackGetAverageBitrate (ctx, 1) / 1000));
    deadbeef->pl_add_meta (it, ":BITRATE", s);
    snprintf (s, sizeof (s), "%s", (WavpackGetMode (ctx) & MODE_FLOAT) ? "FLOAT" : "INTEGER");
    deadbeef->pl_add_meta (it, ":WAVPACK_MODE", s);

    // embedded cue
    deadbeef->pl_lock ();
    const char *cuesheet = deadbeef->pl_find_meta (it, "cuesheet");
    if (cuesheet) {
        trace ("found cuesheet: %s\n", cuesheet);
        DB_playItem_t *last = deadbeef->plt_insert_cue_from_buffer (plt, after, it, cuesheet, strlen (cuesheet), totalsamples, samplerate);
        if (last) {
            deadbeef->pl_unlock ();
            deadbeef->fclose (fp);
            WavpackCloseFile (ctx);
            deadbeef->pl_item_unref (it);
            deadbeef->pl_item_unref (last);
            return last;
        }
    }
    deadbeef->pl_unlock ();
    // cue file on disc
    DB_playItem_t *cue_after = deadbeef->plt_insert_cue (plt, after, it, totalsamples, samplerate);
    if (cue_after) {
        deadbeef->fclose (fp);
        WavpackCloseFile (ctx);
        deadbeef->pl_item_unref (it);
        deadbeef->pl_item_unref (cue_after);
        return cue_after;
    }

    after = deadbeef->plt_insert_item (plt, after, it);
    deadbeef->pl_item_unref (it);

    deadbeef->fclose (fp);
    WavpackCloseFile (ctx);
    return after;
}
Esempio n. 11
0
static int
wv_init (DB_fileinfo_t *_info, DB_playItem_t *it) {
    wvctx_t *info = (wvctx_t *)_info;
    deadbeef->pl_lock ();
    info->file = deadbeef->fopen (deadbeef->pl_find_meta (it, ":URI"));
    deadbeef->pl_unlock ();
    if (!info->file) {
        return -1;
    }

#ifndef TINYWV
    deadbeef->pl_lock ();
    const char *uri = deadbeef->pl_find_meta (it, ":URI");
    char *c_fname = alloca (strlen (uri) + 2);
    if (c_fname) {
        strcpy (c_fname, uri);
        strcat (c_fname, "c");
        info->c_file = deadbeef->fopen (c_fname);
    }
    else {
        fprintf (stderr, "wavpack warning: failed to alloc memory for correction file name\n");
    }
    deadbeef->pl_unlock ();
#endif

    char error[80];
#ifdef TINYWV
    info->ctx = WavpackOpenFileInput (wv_read_stream, info->file, error);
#else
    info->ctx = WavpackOpenFileInputEx (&wsr, info->file, info->c_file, error, OPEN_NORMALIZE, 0);
#endif
    if (!info->ctx) {
        fprintf (stderr, "wavpack error: %s\n", error);
        return -1;
    }
    _info->plugin = &plugin;
    _info->fmt.bps = WavpackGetBytesPerSample (info->ctx) * 8;
    _info->fmt.channels = WavpackGetNumChannels (info->ctx);
    _info->fmt.samplerate = WavpackGetSampleRate (info->ctx);
    _info->fmt.is_float = (WavpackGetMode (info->ctx) & MODE_FLOAT) ? 1 : 0;

    // FIXME: streamer and maybe output plugins need to be fixed to support
    // arbitrary channelmask

    // _info->fmt.channelmask = WavpackGetChannelMask (info->ctx);

    for (int i = 0; i < _info->fmt.channels; i++) {
        _info->fmt.channelmask |= 1 << i;
    }
    _info->readpos = 0;
    if (it->endsample > 0) {
        info->startsample = it->startsample;
        info->endsample = it->endsample;
        if (plugin.seek_sample (_info, 0) < 0) {
            return -1;
        }
    }
    else {
        info->startsample = 0;
        info->endsample = WavpackGetNumSamples (info->ctx)-1;
    }
    return 0;
}
Esempio n. 12
0
static gboolean
xmms_wavpack_init (xmms_xform_t *xform)
{
	xmms_wavpack_data_t *data;
	xmms_sample_format_t sample_format;
	gint samplerate;
	/* the maximum length of error really isn't defined... stupid */
	gchar error[1024];

	g_return_val_if_fail (xform, FALSE);

	if (!xmms_apetag_read (xform)) {
		XMMS_DBG ("Failed to read APEv2 tag");
	}

	data = g_new0 (xmms_wavpack_data_t, 1);
	g_return_val_if_fail (data, FALSE);

	xmms_xform_private_data_set (xform, data);

	data->reader.read_bytes = wavpack_read_bytes;
	data->reader.get_pos = wavpack_get_pos;
	data->reader.set_pos_abs = wavpack_set_pos_abs;
	data->reader.set_pos_rel = wavpack_set_pos_rel;
	data->reader.push_back_byte = wavpack_push_back_byte;
	data->reader.get_length = wavpack_get_length;
	data->reader.can_seek = wavpack_can_seek;

	data->ctx = WavpackOpenFileInputEx (&data->reader,
	                                    xform, xform,
	                                    error, OPEN_TAGS, 0);

	if (!data->ctx) {
		xmms_log_error ("Unable to open wavpack file: %s", error);
		xmms_xform_private_data_set (xform, NULL);
		xmms_wavpack_free_data (data);
		return FALSE;
	}

	data->channels = WavpackGetNumChannels (data->ctx);
	data->bits_per_sample = WavpackGetBitsPerSample (data->ctx);
	data->num_samples = WavpackGetNumSamples (data->ctx);
	samplerate = WavpackGetSampleRate (data->ctx);

	xmms_xform_metadata_set_int (xform,
	                             XMMS_MEDIALIB_ENTRY_PROPERTY_DURATION,
	                             (int) (1000.0 * data->num_samples / samplerate));
	xmms_xform_metadata_set_int (xform,
	                             XMMS_MEDIALIB_ENTRY_PROPERTY_SAMPLERATE,
	                             samplerate);
	xmms_xform_metadata_set_int (xform,
	                             XMMS_MEDIALIB_ENTRY_PROPERTY_BITRATE,
	                             (int) WavpackGetAverageBitrate (data->ctx, FALSE));

	switch (data->bits_per_sample) {
	case 8:
		sample_format = XMMS_SAMPLE_FORMAT_S8;
		break;
	case 12:
	case 16:
		sample_format = XMMS_SAMPLE_FORMAT_S16;
		break;
	case 24:
	case 32:
		sample_format = XMMS_SAMPLE_FORMAT_S32;
		break;
	default:
		xmms_log_error ("Unsupported bits-per-sample in wavpack file: %d",
		                data->bits_per_sample);
		xmms_xform_private_data_set (xform, NULL);
		xmms_wavpack_free_data (data);
		return FALSE;
	}

	xmms_xform_outdata_type_add (xform,
	                             XMMS_STREAM_TYPE_MIMETYPE,
	                             "audio/pcm",
	                             XMMS_STREAM_TYPE_FMT_FORMAT,
	                             sample_format,
	                             XMMS_STREAM_TYPE_FMT_CHANNELS,
	                             data->channels,
	                             XMMS_STREAM_TYPE_FMT_SAMPLERATE,
	                             samplerate,
	                             XMMS_STREAM_TYPE_END);

	return TRUE;
}
bool WavPackDecoder::Open(CFErrorRef *error)
{
	if(IsOpen()) {
		log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger("org.sbooth.AudioEngine.AudioDecoder.WavPack");
		LOG4CXX_WARN(logger, "Open() called on an AudioDecoder that is already open");		
		return true;
	}

	// Ensure the input source is open
	if(!mInputSource->IsOpen() && !mInputSource->Open(error))
		return false;

	mStreamReader.read_bytes = read_bytes_callback;
	mStreamReader.get_pos = get_pos_callback;
	mStreamReader.set_pos_abs = set_pos_abs_callback;
	mStreamReader.set_pos_rel = set_pos_rel_callback;
	mStreamReader.push_back_byte = push_back_byte_callback;
	mStreamReader.get_length = get_length_callback;
	mStreamReader.can_seek = can_seek_callback;
	
	char errorBuf [80];
	
	// Setup converter
	mWPC = WavpackOpenFileInputEx(&mStreamReader, this, NULL, errorBuf, OPEN_WVC | OPEN_NORMALIZE, 0);
	if(NULL == mWPC) {
		if(error) {
			CFMutableDictionaryRef errorDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 
																			   32,
																			   &kCFTypeDictionaryKeyCallBacks,
																			   &kCFTypeDictionaryValueCallBacks);
			
			CFStringRef displayName = CreateDisplayNameForURL(mInputSource->GetURL());
			CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault, 
															   NULL, 
															   CFCopyLocalizedString(CFSTR("The file “%@” is not a valid WavPack file."), ""), 
															   displayName);
			
			CFDictionarySetValue(errorDictionary, 
								 kCFErrorLocalizedDescriptionKey, 
								 errorString);
			
			CFDictionarySetValue(errorDictionary, 
								 kCFErrorLocalizedFailureReasonKey, 
								 CFCopyLocalizedString(CFSTR("Not a WavPack file"), ""));
			
			CFDictionarySetValue(errorDictionary, 
								 kCFErrorLocalizedRecoverySuggestionKey, 
								 CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""));
			
			CFRelease(errorString), errorString = NULL;
			CFRelease(displayName), displayName = NULL;
			
			*error = CFErrorCreate(kCFAllocatorDefault, 
								   AudioDecoderErrorDomain, 
								   AudioDecoderInputOutputError, 
								   errorDictionary);
			
			CFRelease(errorDictionary), errorDictionary = NULL;				
		}
		
		return false;
	}
	
	// Floating-point and lossy files will be handed off in the canonical Core Audio format
	int mode = WavpackGetMode(mWPC);
	if(MODE_FLOAT & mode || !(MODE_LOSSLESS & mode)) {
		// Canonical Core Audio format
		mFormat.mFormatID			= kAudioFormatLinearPCM;
		mFormat.mFormatFlags		= kAudioFormatFlagsNativeFloatPacked | kAudioFormatFlagIsNonInterleaved;
		
		mFormat.mSampleRate			= WavpackGetSampleRate(mWPC);
		mFormat.mChannelsPerFrame	= WavpackGetNumChannels(mWPC);		
		mFormat.mBitsPerChannel		= 8 * sizeof(float);
		
		mFormat.mBytesPerPacket		= (mFormat.mBitsPerChannel / 8);
		mFormat.mFramesPerPacket	= 1;
		mFormat.mBytesPerFrame		= mFormat.mBytesPerPacket * mFormat.mFramesPerPacket;
		
		mFormat.mReserved			= 0;
	}
	else {
		mFormat.mFormatID			= kAudioFormatLinearPCM;
		mFormat.mFormatFlags		= kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsAlignedHigh | kAudioFormatFlagIsNonInterleaved;
		
		mFormat.mSampleRate			= WavpackGetSampleRate(mWPC);
		mFormat.mChannelsPerFrame	= WavpackGetNumChannels(mWPC);
		mFormat.mBitsPerChannel		= WavpackGetBitsPerSample(mWPC);
		
		mFormat.mBytesPerPacket		= sizeof(int32_t);
		mFormat.mFramesPerPacket	= 1;
		mFormat.mBytesPerFrame		= mFormat.mBytesPerPacket * mFormat.mFramesPerPacket;
		
		mFormat.mReserved			= 0;
	}
	
	mTotalFrames						= WavpackGetNumSamples(mWPC);
	
	// Set up the source format
	mSourceFormat.mFormatID				= 'WVPK';
	
	mSourceFormat.mSampleRate			= WavpackGetSampleRate(mWPC);
	mSourceFormat.mChannelsPerFrame		= WavpackGetNumChannels(mWPC);
	mSourceFormat.mBitsPerChannel		= WavpackGetBitsPerSample(mWPC);
	
	// Setup the channel layout
	switch(mFormat.mChannelsPerFrame) {
		case 1:		mChannelLayout = CreateChannelLayoutWithTag(kAudioChannelLayoutTag_Mono);			break;
		case 2:		mChannelLayout = CreateChannelLayoutWithTag(kAudioChannelLayoutTag_Stereo);			break;
		case 4:		mChannelLayout = CreateChannelLayoutWithTag(kAudioChannelLayoutTag_Quadraphonic);	break;
	}
	
	mBuffer = static_cast<int32_t *>(calloc(BUFFER_SIZE_FRAMES * mFormat.mChannelsPerFrame, sizeof(int32_t)));

	if(NULL == mBuffer) {
		if(error)
			*error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainPOSIX, ENOMEM, NULL);
		
		return false;		
	}

	mIsOpen = true;
	return true;
}
Esempio n. 14
0
static GstFlowReturn
gst_wavpack_dec_handle_frame (GstAudioDecoder * bdec, GstBuffer * buf)
{
  GstWavpackDec *dec;
  GstBuffer *outbuf = NULL;
  GstFlowReturn ret = GST_FLOW_OK;
  WavpackHeader wph;
  int32_t decoded, unpacked_size;
  gboolean format_changed;
  gint width, depth, i, j, max;
  gint32 *dec_data = NULL;
  guint8 *out_data;
  GstMapInfo map, omap;

  dec = GST_WAVPACK_DEC (bdec);

  g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);

  gst_buffer_map (buf, &map, GST_MAP_READ);

  /* check input, we only accept framed input with complete chunks */
  if (map.size < sizeof (WavpackHeader))
    goto input_not_framed;

  if (!gst_wavpack_read_header (&wph, map.data))
    goto invalid_header;

  if (map.size < wph.ckSize + 4 * 1 + 4)
    goto input_not_framed;

  if (!(wph.flags & INITIAL_BLOCK))
    goto input_not_framed;

  dec->wv_id.buffer = map.data;
  dec->wv_id.length = map.size;
  dec->wv_id.position = 0;

  /* create a new wavpack context if there is none yet but if there
   * was already one (i.e. caps were set on the srcpad) check whether
   * the new one has the same caps */
  if (!dec->context) {
    gchar error_msg[80];

    dec->context = WavpackOpenFileInputEx (dec->stream_reader,
        &dec->wv_id, NULL, error_msg, OPEN_STREAMING, 0);

    /* expect this to work */
    if (!dec->context) {
      GST_WARNING_OBJECT (dec, "Couldn't decode buffer: %s", error_msg);
      goto context_failed;
    }
  }

  g_assert (dec->context != NULL);

  format_changed =
      (dec->sample_rate != WavpackGetSampleRate (dec->context)) ||
      (dec->channels != WavpackGetNumChannels (dec->context)) ||
      (dec->depth != WavpackGetBytesPerSample (dec->context) * 8) ||
      (dec->channel_mask != WavpackGetChannelMask (dec->context));

  if (!gst_pad_has_current_caps (GST_AUDIO_DECODER_SRC_PAD (dec)) ||
      format_changed) {
    gint channel_mask;

    dec->sample_rate = WavpackGetSampleRate (dec->context);
    dec->channels = WavpackGetNumChannels (dec->context);
    dec->depth = WavpackGetBytesPerSample (dec->context) * 8;

    channel_mask = WavpackGetChannelMask (dec->context);
    if (channel_mask == 0)
      channel_mask = gst_wavpack_get_default_channel_mask (dec->channels);

    dec->channel_mask = channel_mask;

    gst_wavpack_dec_negotiate (dec);

    /* send GST_TAG_AUDIO_CODEC and GST_TAG_BITRATE tags before something
     * is decoded or after the format has changed */
    gst_wavpack_dec_post_tags (dec);
  }

  /* alloc output buffer */
  dec_data = g_malloc (4 * wph.block_samples * dec->channels);

  /* decode */
  decoded = WavpackUnpackSamples (dec->context, dec_data, wph.block_samples);
  if (decoded != wph.block_samples)
    goto decode_error;

  unpacked_size = (dec->width / 8) * wph.block_samples * dec->channels;
  outbuf = gst_buffer_new_and_alloc (unpacked_size);

  /* legacy; pass along offset, whatever that might entail */
  GST_BUFFER_OFFSET (outbuf) = GST_BUFFER_OFFSET (buf);

  gst_buffer_map (outbuf, &omap, GST_MAP_WRITE);
  out_data = omap.data;

  width = dec->width;
  depth = dec->depth;
  max = dec->channels * wph.block_samples;
  if (width == 8) {
    gint8 *outbuffer = (gint8 *) out_data;
    gint *reorder_map = dec->channel_reorder_map;

    for (i = 0; i < max; i += dec->channels) {
      for (j = 0; j < dec->channels; j++)
        *outbuffer++ = (gint8) (dec_data[i + reorder_map[j]]);
    }
  } else if (width == 16) {
    gint16 *outbuffer = (gint16 *) out_data;
    gint *reorder_map = dec->channel_reorder_map;

    for (i = 0; i < max; i += dec->channels) {
      for (j = 0; j < dec->channels; j++)
        *outbuffer++ = (gint16) (dec_data[i + reorder_map[j]]);
    }
  } else if (dec->width == 32) {
    gint32 *outbuffer = (gint32 *) out_data;
    gint *reorder_map = dec->channel_reorder_map;

    if (width != depth) {
      for (i = 0; i < max; i += dec->channels) {
        for (j = 0; j < dec->channels; j++)
          *outbuffer++ =
              (gint32) (dec_data[i + reorder_map[j]] << (width - depth));
      }
    } else {
      for (i = 0; i < max; i += dec->channels) {
        for (j = 0; j < dec->channels; j++)
          *outbuffer++ = (gint32) (dec_data[i + reorder_map[j]]);
      }
    }
  } else {
    g_assert_not_reached ();
  }

  gst_buffer_unmap (outbuf, &omap);
  gst_buffer_unmap (buf, &map);
  buf = NULL;

  g_free (dec_data);

  ret = gst_audio_decoder_finish_frame (bdec, outbuf, 1);

out:
  if (buf)
    gst_buffer_unmap (buf, &map);

  if (G_UNLIKELY (ret != GST_FLOW_OK)) {
    GST_DEBUG_OBJECT (dec, "flow: %s", gst_flow_get_name (ret));
  }

  return ret;

/* ERRORS */
input_not_framed:
  {
    GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), ("Expected framed input"));
    ret = GST_FLOW_ERROR;
    goto out;
  }
invalid_header:
  {
    GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), ("Invalid wavpack header"));
    ret = GST_FLOW_ERROR;
    goto out;
  }
context_failed:
  {
    GST_AUDIO_DECODER_ERROR (bdec, 1, LIBRARY, INIT, (NULL),
        ("error creating Wavpack context"), ret);
    goto out;
  }
decode_error:
  {
    const gchar *reason = "unknown";

    if (dec->context) {
      reason = WavpackGetErrorMessage (dec->context);
    } else {
      reason = "couldn't create decoder context";
    }
    GST_AUDIO_DECODER_ERROR (bdec, 1, STREAM, DECODE, (NULL),
        ("decoding error: %s", reason), ret);
    g_free (dec_data);
    if (ret == GST_FLOW_OK)
      gst_audio_decoder_finish_frame (bdec, NULL, 1);
    goto out;
  }
}
Esempio n. 15
0
int CSound::DecodeWV(int SampleID, const void *pData, unsigned DataSize)
{
	if(SampleID == -1 || SampleID >= NUM_SAMPLES)
		return -1;

	CSample *pSample = &m_aSamples[SampleID];
	char aError[100];
	WavpackContext *pContext;

	ms_pWVBuffer = pData;
	ms_WVBufferSize = DataSize;
	ms_WVBufferPosition = 0;

	pContext = WavpackOpenFileInput(ReadData, aError);
	if (pContext)
	{
		int NumSamples = WavpackGetNumSamples(pContext);
		int BitsPerSample = WavpackGetBitsPerSample(pContext);
		unsigned int SampleRate = WavpackGetSampleRate(pContext);
		int NumChannels = WavpackGetNumChannels(pContext);
		int *pSrc;
		short *pDst;
		int i;

		pSample->m_Channels = NumChannels;
		pSample->m_Rate = SampleRate;

		if(pSample->m_Channels > 2)
		{
			dbg_msg("sound/wv", "file is not mono or stereo.");
			return -1;
		}

		if(BitsPerSample != 16)
		{
			dbg_msg("sound/wv", "bps is %d, not 16", BitsPerSample);
			return -1;
		}

		int *pBuffer = (int *)mem_alloc(4*NumSamples*NumChannels, 1);
		WavpackUnpackSamples(pContext, pBuffer, NumSamples); // TODO: check return value
		pSrc = pBuffer;

		pSample->m_pData = (short *)mem_alloc(2*NumSamples*NumChannels, 1);
		pDst = pSample->m_pData;

		for (i = 0; i < NumSamples*NumChannels; i++)
			*pDst++ = (short)*pSrc++;

		mem_free(pBuffer);

		pSample->m_NumFrames = NumSamples;
		pSample->m_LoopStart = -1;
		pSample->m_LoopEnd = -1;
		pSample->m_PausedAt = 0;
	}
	else
	{
		dbg_msg("sound/wv", "failed to decode sample (%s)", aError);
		return -1;
	}

	return SampleID;
}
Esempio n. 16
0
int snd_load_wv(const char *filename)
{
	SAMPLE *snd;
	int sid = -1;
	char error[100];
	WavpackContext *context;
	
	/* don't waste memory on sound when we are stress testing */
	if(config.dbg_stress)
		return -1;
		
	/* no need to load sound when we are running with no sound */
	if(!sound_enabled)
		return 1;

	file = engine_openfile(filename, IOFLAG_READ); /* TODO: use system.h stuff for this */
	if(!file)
	{
		dbg_msg("sound/wv", "failed to open %s", filename);
		return -1;
	}

	sid = snd_alloc_id();
	if(sid < 0)
		return -1;
	snd = &samples[sid];

	context = WavpackOpenFileInput(read_data, error);
	if (context)
	{
		int samples = WavpackGetNumSamples(context);
		int bitspersample = WavpackGetBitsPerSample(context);
		unsigned int samplerate = WavpackGetSampleRate(context);
		int channels = WavpackGetNumChannels(context);
		int *data;
		int *src;
		short *dst;
		int i;

		snd->channels = channels;
		snd->rate = samplerate;

		if(snd->channels > 2)
		{
			dbg_msg("sound/wv", "file is not mono or stereo. filename='%s'", filename);
			return -1;
		}

		/*
		if(snd->rate != 44100)
		{
			dbg_msg("sound/wv", "file is %d Hz, not 44100 Hz. filename='%s'", snd->rate, filename);
			return -1;
		}*/
		
		if(bitspersample != 16)
		{
			dbg_msg("sound/wv", "bps is %d, not 16, filname='%s'", bitspersample, filename);
			return -1;
		}

		data = (int *)mem_alloc(4*samples*channels, 1);
		WavpackUnpackSamples(context, data, samples); /* TODO: check return value */
		src = data;
		
		snd->data = (short *)mem_alloc(2*samples*channels, 1);
		dst = snd->data;

		for (i = 0; i < samples*channels; i++)
			*dst++ = (short)*src++;

		mem_free(data);

		snd->num_frames = samples;
		snd->loop_start = -1;
		snd->loop_end = -1;
	}
	else
	{
		dbg_msg("sound/wv", "failed to open %s: %s", filename, error);
	}

	io_close(file);
	file = NULL;

	if(config.debug)
		dbg_msg("sound/wv", "loaded %s", filename);

	rate_convert(sid);
	return sid;
}
Esempio n. 17
0
HRESULT CWavPackDSDecoder::Receive(IMediaSample *pSample)
{
    //  Check for other streams and pass them on 
    AM_SAMPLE2_PROPERTIES * const pProps = m_pInput->SampleProps(); 
    if ((pProps->dwStreamId != AM_STREAM_MEDIA) &&
        (pProps->dwStreamId != AM_STREAM_BLOCK_ADDITIONNAL))
    {
        return m_pOutput->Deliver(pSample);
    }
    
    ASSERT(pSample);
    // If no output to deliver to then no point sending us data 
    ASSERT(m_pOutput != NULL);

    HRESULT hr = S_OK;
    BYTE *pSrc, *pDst;
    DWORD SrcLength = pSample->GetActualDataLength();
    hr = pSample->GetPointer(&pSrc);
    if(FAILED(hr))
        return hr;
    
     // Check for minimal block size
    if(SrcLength < (3 * sizeof(uint32_t)))
    {
        return S_OK;
    }

    WAVEFORMATEX* pwfx = (WAVEFORMATEX*)m_pInput->CurrentMediaType().Format();
    BOOL bSeveralBlocks = (pwfx->nChannels > 2);
 
    if(pProps->dwStreamId == AM_STREAM_MEDIA)
    {
        REFERENCE_TIME rtStop;
        if(pSample->IsSyncPoint() == S_OK)
        {
            pSample->GetTime(&m_rtFrameStart, &rtStop);
            m_TotalSamples = 0;
        }

        m_MainBlockDiscontinuity = (pSample->IsDiscontinuity() == S_OK);

        reconstruct_wavpack_frame(
            m_MainFrame,
            &m_CommonFrameData,
            (char*)pSrc,
            SrcLength,            
            TRUE,
            bSeveralBlocks,
            m_PrivateData.version);

        if(m_HybridMode == TRUE)
        {
            // Stop here and wait for correction data
            return S_OK;
        }
    }
    
    if((m_HybridMode == TRUE) && 
       (pProps->dwStreamId == AM_STREAM_BLOCK_ADDITIONNAL))
    {
        // rebuild correction data block
        reconstruct_wavpack_frame(
            m_CorrectionFrame,
            &m_CommonFrameData,
            (char*)pSrc,
            SrcLength,
            FALSE,
            bSeveralBlocks,
            m_PrivateData.version);
    }

    if(wavpack_buffer_decoder_load_frame(m_Codec, m_MainFrame->data, m_MainFrame->len,
        m_HybridMode ? m_CorrectionFrame->data : NULL, m_CorrectionFrame->len) == 0)
    {
        // Something is wrong
        return S_FALSE;
    }
   
    // We can precise the decoding mode now
    if(m_HybridMode == FALSE)
    {
        if(m_CommonFrameData.array_flags[0] & WV_HYBRID_FLAG)
        {
            m_DecodingMode = DECODING_MODE_LOSSY;
        }
        else
        {
            m_DecodingMode = DECODING_MODE_LOSSLESS;
        }
    }

    uint32_t samplesLeft = m_CommonFrameData.block_samples;
    while(samplesLeft > 0)
    {
        // Set up the output sample
        IMediaSample *pOutSample;
        hr = InitializeOutputSample(pSample, &pOutSample);
        if(FAILED(hr))
        {
            break;
        }
    
        DWORD DstLength = pOutSample->GetSize();
        hr = pOutSample->GetPointer(&pDst);
        if(FAILED(hr))
        {
            pOutSample->Release();
            break;
        }

        DstLength &= 0xFFFFFFF8;
    
        long samples = wavpack_buffer_decoder_unpack(m_Codec,(int32_t *)pDst, m_SamplesPerBuffer);
        if(samples)
        {
            wavpack_buffer_format_samples(m_Codec,
                (uchar *) pDst,
                (long*) pDst,
                samples);
            
            DstLength = samples *
                WavpackGetBytesPerSample(m_Codec->wpc) *
                WavpackGetNumChannels (m_Codec->wpc);

            pOutSample->SetActualDataLength(DstLength);
            
            REFERENCE_TIME rtStart, rtStop;
            rtStart = m_rtFrameStart + (REFERENCE_TIME)(((double)m_TotalSamples / WavpackGetSampleRate(m_Codec->wpc)) * 10000000);
            m_TotalSamples += samples;
            rtStop = m_rtFrameStart + (REFERENCE_TIME)(((double)m_TotalSamples / WavpackGetSampleRate(m_Codec->wpc)) * 10000000);

            if(rtStart < 0 && rtStop < 0)
            {
                // No need to deliver this sample it will be skipped
                pOutSample->Release();
                continue;
            }
            pOutSample->SetTime(&rtStart, &rtStop);
            pOutSample->SetSyncPoint(TRUE);
            pOutSample->SetDiscontinuity(m_MainBlockDiscontinuity);
            if(m_MainBlockDiscontinuity == TRUE)
            {
                m_MainBlockDiscontinuity = FALSE;
            }

            hr = m_pOutput->Deliver(pOutSample);
            if(FAILED(hr))
            {
                pOutSample->Release();
                break;
            }
            pOutSample->Release();
        }
        else
        {
            pOutSample->Release();
            break;
        }
        samplesLeft -= samples;
    }
    
    m_DecodedFrames++;
    m_CrcError = WavpackGetNumErrors(m_Codec->wpc);
    
    return S_OK;
}
Esempio n. 18
0
/*
 * This does the main decoding thing.
 * Requires an already opened WavpackContext.
 */
static void
wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek)
{
	GError *error = NULL;
	bool is_float;
	enum sample_format sample_format;
	struct audio_format audio_format;
	format_samples_t format_samples;
	float total_time;
	int bytes_per_sample, output_sample_size;

	is_float = (WavpackGetMode(wpc) & MODE_FLOAT) != 0;
	sample_format =
		wavpack_bits_to_sample_format(is_float,
					      WavpackGetBytesPerSample(wpc));

	if (!audio_format_init_checked(&audio_format,
				       WavpackGetSampleRate(wpc),
				       sample_format,
				       WavpackGetNumChannels(wpc), &error)) {
		g_warning("%s", error->message);
		g_error_free(error);
		return;
	}

	if (is_float) {
		format_samples = format_samples_float;
	} else {
		format_samples = format_samples_int;
	}

	total_time = WavpackGetNumSamples(wpc);
	total_time /= audio_format.sample_rate;
	bytes_per_sample = WavpackGetBytesPerSample(wpc);
	output_sample_size = audio_format_frame_size(&audio_format);

	/* wavpack gives us all kind of samples in a 32-bit space */
	int32_t chunk[1024];
	const uint32_t samples_requested = G_N_ELEMENTS(chunk) /
		audio_format.channels;

	decoder_initialized(decoder, &audio_format, can_seek, total_time);

	enum decoder_command cmd = decoder_get_command(decoder);
	while (cmd != DECODE_COMMAND_STOP) {
		if (cmd == DECODE_COMMAND_SEEK) {
			if (can_seek) {
				unsigned where = decoder_seek_where(decoder) *
					audio_format.sample_rate;

				if (WavpackSeekSample(wpc, where)) {
					decoder_command_finished(decoder);
				} else {
					decoder_seek_error(decoder);
				}
			} else {
				decoder_seek_error(decoder);
			}
		}

		uint32_t samples_got = WavpackUnpackSamples(wpc, chunk,
							    samples_requested);
		if (samples_got == 0)
			break;

		int bitrate = (int)(WavpackGetInstantBitrate(wpc) / 1000 +
				    0.5);
		format_samples(bytes_per_sample, chunk,
			       samples_got * audio_format.channels);

		cmd = decoder_data(decoder, NULL, chunk,
				   samples_got * output_sample_size,
				   bitrate);
	}
}
Esempio n. 19
0
static bool_t wv_play (InputPlayback * playback, const char * filename,
 VFSFile * file, int start_time, int stop_time, bool_t pause)
{
    if (file == NULL)
        return FALSE;

    int32_t *input = NULL;
    void *output = NULL;
    int sample_rate, num_channels, bits_per_sample;
    unsigned num_samples;
    WavpackContext *ctx = NULL;
    VFSFile *wvc_input = NULL;
    bool_t error = FALSE;

    if (! wv_attach (filename, file, & wvc_input, & ctx, NULL, OPEN_TAGS |
     OPEN_WVC))
    {
        fprintf (stderr, "Error opening Wavpack file '%s'.", filename);
        error = TRUE;
        goto error_exit;
    }

    sample_rate = WavpackGetSampleRate(ctx);
    num_channels = WavpackGetNumChannels(ctx);
    bits_per_sample = WavpackGetBitsPerSample(ctx);
    num_samples = WavpackGetNumSamples(ctx);

    if (!playback->output->open_audio(SAMPLE_FMT(bits_per_sample), sample_rate, num_channels))
    {
        fprintf (stderr, "Error opening audio output.");
        error = TRUE;
        goto error_exit;
    }

    if (pause)
        playback->output->pause(TRUE);

    input = malloc(BUFFER_SIZE * num_channels * sizeof(uint32_t));
    output = malloc(BUFFER_SIZE * num_channels * SAMPLE_SIZE(bits_per_sample));
    if (input == NULL || output == NULL)
        goto error_exit;

    playback->set_gain_from_playlist(playback);

    pthread_mutex_lock (& mutex);

    playback->set_params(playback, (int) WavpackGetAverageBitrate(ctx, num_channels),
        sample_rate, num_channels);

    seek_value = (start_time > 0) ? start_time : -1;
    stop_flag = FALSE;

    playback->set_pb_ready(playback);

    pthread_mutex_unlock (& mutex);

    while (!stop_flag && (stop_time < 0 ||
     playback->output->written_time () < stop_time))
    {
        int ret;
        unsigned samples_left;

        /* Handle seek and pause requests */
        pthread_mutex_lock (& mutex);

        if (seek_value >= 0)
        {
            playback->output->flush (seek_value);
            WavpackSeekSample (ctx, (int64_t) seek_value * sample_rate / 1000);
            seek_value = -1;
        }

        pthread_mutex_unlock (& mutex);

        /* Decode audio data */
        samples_left = num_samples - WavpackGetSampleIndex(ctx);

        ret = WavpackUnpackSamples(ctx, input, BUFFER_SIZE);
        if (samples_left == 0)
            stop_flag = TRUE;
        else if (ret < 0)
        {
            fprintf (stderr, "Error decoding file.\n");
            break;
        }
        else
        {
            /* Perform audio data conversion and output */
            unsigned i;
            int32_t *rp = input;
            int8_t *wp = output;
            int16_t *wp2 = output;
            int32_t *wp4 = output;

            if (bits_per_sample == 8)
            {
                for (i = 0; i < ret * num_channels; i++, wp++, rp++)
                    *wp = *rp & 0xff;
            }
            else if (bits_per_sample == 16)
            {
                for (i = 0; i < ret * num_channels; i++, wp2++, rp++)
                    *wp2 = *rp & 0xffff;
            }
            else if (bits_per_sample == 24 || bits_per_sample == 32)
            {
                for (i = 0; i < ret * num_channels; i++, wp4++, rp++)
                    *wp4 = *rp;
            }

            playback->output->write_audio(output, ret * num_channels * SAMPLE_SIZE(bits_per_sample));
        }
    }

error_exit:

    free(input);
    free(output);
    wv_deattach (wvc_input, ctx);

    stop_flag = TRUE;
    return ! error;
}
Esempio n. 20
0
bool WavPackDecoder::Open(CFErrorRef *error)
{
	if(IsOpen()) {
		LOGGER_WARNING("org.sbooth.AudioEngine.AudioDecoder.WavPack", "Open() called on an AudioDecoder that is already open");		
		return true;
	}

	// Ensure the input source is open
	if(!mInputSource->IsOpen() && !mInputSource->Open(error))
		return false;

	mStreamReader.read_bytes = read_bytes_callback;
	mStreamReader.get_pos = get_pos_callback;
	mStreamReader.set_pos_abs = set_pos_abs_callback;
	mStreamReader.set_pos_rel = set_pos_rel_callback;
	mStreamReader.push_back_byte = push_back_byte_callback;
	mStreamReader.get_length = get_length_callback;
	mStreamReader.can_seek = can_seek_callback;
	
	char errorBuf [80];
	
	// Setup converter
	mWPC = WavpackOpenFileInputEx(&mStreamReader, this, nullptr, errorBuf, OPEN_WVC | OPEN_NORMALIZE, 0);
	if(nullptr == mWPC) {
		if(error) {
			CFStringRef description = CFCopyLocalizedString(CFSTR("The file “%@” is not a valid WavPack file."), "");
			CFStringRef failureReason = CFCopyLocalizedString(CFSTR("Not a WavPack file"), "");
			CFStringRef recoverySuggestion = CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), "");
			
			*error = CreateErrorForURL(AudioDecoderErrorDomain, AudioDecoderInputOutputError, description, mInputSource->GetURL(), failureReason, recoverySuggestion);
			
			CFRelease(description), description = nullptr;
			CFRelease(failureReason), failureReason = nullptr;
			CFRelease(recoverySuggestion), recoverySuggestion = nullptr;
		}
		
		return false;
	}
	
	// Floating-point and lossy files will be handed off in the canonical Core Audio format
	int mode = WavpackGetMode(mWPC);
	if(MODE_FLOAT & mode || !(MODE_LOSSLESS & mode)) {
		// Canonical Core Audio format
		mFormat.mFormatID			= kAudioFormatLinearPCM;
		mFormat.mFormatFlags		= kAudioFormatFlagsNativeFloatPacked | kAudioFormatFlagIsNonInterleaved;
		
		mFormat.mSampleRate			= WavpackGetSampleRate(mWPC);
		mFormat.mChannelsPerFrame	= WavpackGetNumChannels(mWPC);		
		mFormat.mBitsPerChannel		= 8 * sizeof(float);
		
		mFormat.mBytesPerPacket		= (mFormat.mBitsPerChannel / 8);
		mFormat.mFramesPerPacket	= 1;
		mFormat.mBytesPerFrame		= mFormat.mBytesPerPacket * mFormat.mFramesPerPacket;
		
		mFormat.mReserved			= 0;
	}
	else {
		mFormat.mFormatID			= kAudioFormatLinearPCM;
		mFormat.mFormatFlags		= kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsNonInterleaved;

		// Don't set kAudioFormatFlagIsAlignedHigh for 32-bit integer files
		mFormat.mFormatFlags		|= (32 == WavpackGetBitsPerSample(mWPC) ? kAudioFormatFlagIsPacked : kAudioFormatFlagIsAlignedHigh);

		mFormat.mSampleRate			= WavpackGetSampleRate(mWPC);
		mFormat.mChannelsPerFrame	= WavpackGetNumChannels(mWPC);
		mFormat.mBitsPerChannel		= WavpackGetBitsPerSample(mWPC);
		
		mFormat.mBytesPerPacket		= sizeof(int32_t);
		mFormat.mFramesPerPacket	= 1;
		mFormat.mBytesPerFrame		= mFormat.mBytesPerPacket * mFormat.mFramesPerPacket;
		
		mFormat.mReserved			= 0;
	}
	
	mTotalFrames						= WavpackGetNumSamples(mWPC);
	
	// Set up the source format
	mSourceFormat.mFormatID				= 'WVPK';
	
	mSourceFormat.mSampleRate			= WavpackGetSampleRate(mWPC);
	mSourceFormat.mChannelsPerFrame		= WavpackGetNumChannels(mWPC);
	mSourceFormat.mBitsPerChannel		= WavpackGetBitsPerSample(mWPC);
	
	// Setup the channel layout
	switch(mFormat.mChannelsPerFrame) {
		case 1:		mChannelLayout = CreateChannelLayoutWithTag(kAudioChannelLayoutTag_Mono);			break;
		case 2:		mChannelLayout = CreateChannelLayoutWithTag(kAudioChannelLayoutTag_Stereo);			break;
		case 4:		mChannelLayout = CreateChannelLayoutWithTag(kAudioChannelLayoutTag_Quadraphonic);	break;
	}
	
	mBuffer = static_cast<int32_t *>(calloc(BUFFER_SIZE_FRAMES * mFormat.mChannelsPerFrame, sizeof(int32_t)));

	if(nullptr == mBuffer) {
		if(error)
			*error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainPOSIX, ENOMEM, nullptr);
		
		return false;		
	}

	mIsOpen = true;
	return true;
}
Esempio n. 21
0
static gboolean
gst_wavpack_parse_create_src_pad (GstWavpackParse * wvparse, GstBuffer * buf,
    WavpackHeader * header)
{
  GstWavpackMetadata meta;

  GstCaps *caps = NULL;

  guchar *bufptr;

  g_assert (wvparse->srcpad == NULL);

  bufptr = GST_BUFFER_DATA (buf) + sizeof (WavpackHeader);

  while (gst_wavpack_read_metadata (&meta, GST_BUFFER_DATA (buf), &bufptr)) {
    switch (meta.id) {
      case ID_WVC_BITSTREAM:{
        caps = gst_caps_new_simple ("audio/x-wavpack-correction",
            "framed", G_TYPE_BOOLEAN, TRUE, NULL);
        wvparse->srcpad =
            gst_pad_new_from_template (gst_element_class_get_pad_template
            (GST_ELEMENT_GET_CLASS (wvparse), "wvcsrc"), "wvcsrc");
        break;
      }
      case ID_WV_BITSTREAM:
      case ID_WVX_BITSTREAM:{
        WavpackStreamReader *stream_reader = gst_wavpack_stream_reader_new ();

        WavpackContext *wpc;

        gchar error_msg[80];

        read_id rid;

        gint channel_mask;

        rid.buffer = GST_BUFFER_DATA (buf);
        rid.length = GST_BUFFER_SIZE (buf);
        rid.position = 0;

        wpc =
            WavpackOpenFileInputEx (stream_reader, &rid, NULL, error_msg, 0, 0);

        if (!wpc)
          return FALSE;

        wvparse->samplerate = WavpackGetSampleRate (wpc);
        wvparse->channels = WavpackGetNumChannels (wpc);
        wvparse->total_samples =
            (header->total_samples ==
            0xffffffff) ? G_GINT64_CONSTANT (-1) : header->total_samples;

        caps = gst_caps_new_simple ("audio/x-wavpack",
            "width", G_TYPE_INT, WavpackGetBitsPerSample (wpc),
            "channels", G_TYPE_INT, wvparse->channels,
            "rate", G_TYPE_INT, wvparse->samplerate,
            "framed", G_TYPE_BOOLEAN, TRUE, NULL);
#ifdef WAVPACK_OLD_API
        channel_mask = wpc->config.channel_mask;
#else
        channel_mask = WavpackGetChannelMask (wpc);
#endif
        if (channel_mask == 0)
          channel_mask =
              gst_wavpack_get_default_channel_mask (wvparse->channels);

        if (channel_mask != 0) {
          if (!gst_wavpack_set_channel_layout (caps, channel_mask)) {
            GST_WARNING_OBJECT (wvparse, "Failed to set channel layout");
            gst_caps_unref (caps);
            caps = NULL;
            WavpackCloseFile (wpc);
            g_free (stream_reader);
            break;
          }
        }

        wvparse->srcpad =
            gst_pad_new_from_template (gst_element_class_get_pad_template
            (GST_ELEMENT_GET_CLASS (wvparse), "src"), "src");
        WavpackCloseFile (wpc);
        g_free (stream_reader);
        break;
      }
      default:{
        GST_LOG_OBJECT (wvparse, "unhandled ID: 0x%02x", meta.id);
        break;
      }
    }
    if (caps != NULL)
      break;
  }

  if (caps == NULL || wvparse->srcpad == NULL)
    return FALSE;

  GST_DEBUG_OBJECT (wvparse, "Added src pad with caps %" GST_PTR_FORMAT, caps);

  gst_pad_set_query_function (wvparse->srcpad,
      GST_DEBUG_FUNCPTR (gst_wavpack_parse_src_query));
  gst_pad_set_query_type_function (wvparse->srcpad,
      GST_DEBUG_FUNCPTR (gst_wavpack_parse_get_src_query_types));
  gst_pad_set_event_function (wvparse->srcpad,
      GST_DEBUG_FUNCPTR (gst_wavpack_parse_src_event));

  gst_pad_set_caps (wvparse->srcpad, caps);
  gst_caps_unref (caps);
  gst_pad_use_fixed_caps (wvparse->srcpad);

  gst_object_ref (wvparse->srcpad);
  gst_pad_set_active (wvparse->srcpad, TRUE);
  gst_element_add_pad (GST_ELEMENT (wvparse), wvparse->srcpad);
  gst_element_no_more_pads (GST_ELEMENT (wvparse));

  return TRUE;
}
Esempio n. 22
0
static gboolean wv_play (InputPlayback * playback, const gchar * filename,
 VFSFile * file, gint start_time, gint stop_time, gboolean pause)
{
    if (file == NULL)
        return FALSE;

    gint32 *input = NULL;
    void *output = NULL;
    gint sample_rate, num_channels, bits_per_sample;
    guint num_samples;
    WavpackContext *ctx = NULL;
    VFSFile *wvc_input = NULL;
    gboolean error = FALSE;

    if (! wv_attach (filename, file, & wvc_input, & ctx, NULL, OPEN_TAGS |
     OPEN_WVC))
    {
        g_warning("Error opening Wavpack file '%s'.", filename);
        error = TRUE;
        goto error_exit;
    }

    sample_rate = WavpackGetSampleRate(ctx);
    num_channels = WavpackGetNumChannels(ctx);
    bits_per_sample = WavpackGetBitsPerSample(ctx);
    num_samples = WavpackGetNumSamples(ctx);

    if (!playback->output->open_audio(SAMPLE_FMT(bits_per_sample), sample_rate, num_channels))
    {
        g_warning("Error opening audio output.");
        error = TRUE;
        goto error_exit;
    }

    if (pause)
        playback->output->pause(TRUE);

    input = g_malloc(BUFFER_SIZE * num_channels * sizeof(guint32));
    output = g_malloc(BUFFER_SIZE * num_channels * SAMPLE_SIZE(bits_per_sample));
    if (input == NULL || output == NULL)
        goto error_exit;

    playback->set_gain_from_playlist(playback);

    g_mutex_lock(ctrl_mutex);

    playback->set_params(playback, (gint) WavpackGetAverageBitrate(ctx, num_channels),
        sample_rate, num_channels);

    seek_value = (start_time > 0) ? start_time : -1;
    stop_flag = FALSE;

    playback->set_pb_ready(playback);

    g_mutex_unlock(ctrl_mutex);

    while (!stop_flag && (stop_time < 0 ||
     playback->output->written_time () < stop_time))
    {
        gint ret;
        guint samples_left;

        /* Handle seek and pause requests */
        g_mutex_lock(ctrl_mutex);

        if (seek_value >= 0)
        {
            playback->output->flush (seek_value);
            WavpackSeekSample (ctx, (gint64) seek_value * sample_rate / 1000);
            seek_value = -1;
            g_cond_signal(ctrl_cond);
        }

        g_mutex_unlock(ctrl_mutex);

        /* Decode audio data */
        samples_left = num_samples - WavpackGetSampleIndex(ctx);

        ret = WavpackUnpackSamples(ctx, input, BUFFER_SIZE);
        if (samples_left == 0)
            stop_flag = TRUE;
        else if (ret < 0)
        {
            g_warning("Error decoding file.\n");
            break;
        }
        else
        {
            /* Perform audio data conversion and output */
            guint i;
            gint32 *rp = input;
            gint8 *wp = output;
            gint16 *wp2 = output;
            gint32 *wp4 = output;

            if (bits_per_sample == 8)
            {
                for (i = 0; i < ret * num_channels; i++, wp++, rp++)
                    *wp = *rp & 0xff;
            }
            else if (bits_per_sample == 16)
            {
                for (i = 0; i < ret * num_channels; i++, wp2++, rp++)
                    *wp2 = *rp & 0xffff;
            }
            else if (bits_per_sample == 24 || bits_per_sample == 32)
            {
                for (i = 0; i < ret * num_channels; i++, wp4++, rp++)
                    *wp4 = *rp;
            }

            playback->output->write_audio(output, ret * num_channels * SAMPLE_SIZE(bits_per_sample));
        }
    }

    /* Flush buffer */
    g_mutex_lock(ctrl_mutex);

    while (!stop_flag && playback->output->buffer_playing())
        g_usleep(20000);

    g_cond_signal(ctrl_cond);
    g_mutex_unlock(ctrl_mutex);

error_exit:

    g_free(input);
    g_free(output);
    wv_deattach (wvc_input, ctx);

    stop_flag = TRUE;
    playback->output->close_audio();
    return ! error;
}