WMA Voice now plays and seeks in the sim. The code is still in floating point, and is not added to the main build. There's still a bug with the decoder in the current state that it outputs a fewer number of samples than ffmpeg's.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@27744 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
eb369699c6
commit
4ff2cf4f0c
9 changed files with 296 additions and 7 deletions
|
@ -7,6 +7,7 @@
|
||||||
#define ASF_CODEC_ID_WMAV1 0x160
|
#define ASF_CODEC_ID_WMAV1 0x160
|
||||||
#define ASF_CODEC_ID_WMAV2 0x161
|
#define ASF_CODEC_ID_WMAV2 0x161
|
||||||
#define ASF_CODEC_ID_WMAPRO 0x162
|
#define ASF_CODEC_ID_WMAPRO 0x162
|
||||||
|
#define ASF_CODEC_ID_WMAVOICE 0x00A
|
||||||
|
|
||||||
enum asf_error_e {
|
enum asf_error_e {
|
||||||
ASF_ERROR_INTERNAL = -1, /* incorrect input to API calls */
|
ASF_ERROR_INTERNAL = -1, /* incorrect input to API calls */
|
||||||
|
@ -33,7 +34,7 @@ struct asf_waveformatex_s {
|
||||||
uint16_t bitspersample;
|
uint16_t bitspersample;
|
||||||
uint16_t datalen;
|
uint16_t datalen;
|
||||||
uint16_t numpackets;
|
uint16_t numpackets;
|
||||||
uint8_t data[18];
|
uint8_t data[46];
|
||||||
};
|
};
|
||||||
typedef struct asf_waveformatex_s asf_waveformatex_t;
|
typedef struct asf_waveformatex_s asf_waveformatex_t;
|
||||||
|
|
||||||
|
|
17
apps/codecs/libwmavoice/SOURCES
Normal file
17
apps/codecs/libwmavoice/SOURCES
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
acelp_filters.c
|
||||||
|
acelp_vectors.c
|
||||||
|
avfft.c
|
||||||
|
bitstream.c
|
||||||
|
celp_filters.c
|
||||||
|
celp_math.c
|
||||||
|
dct.c
|
||||||
|
fft.c
|
||||||
|
lsp.c
|
||||||
|
mdct.c
|
||||||
|
rdft.c
|
||||||
|
utils.c
|
||||||
|
wmavoice.c
|
||||||
|
libavutil/log.c
|
||||||
|
libavutil/lzo.c
|
||||||
|
libavutil/mem.c
|
||||||
|
libavutil/mathematics.c
|
37
apps/codecs/libwmavoice/libwmavoice.make
Normal file
37
apps/codecs/libwmavoice/libwmavoice.make
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
# __________ __ ___.
|
||||||
|
# Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||||
|
# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||||
|
# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||||
|
# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||||
|
# \/ \/ \/ \/ \/
|
||||||
|
# $Id: libwmavoice.make 27586 2010-07-27 06:48:15Z nls $
|
||||||
|
#
|
||||||
|
|
||||||
|
# libwmavoice
|
||||||
|
WMAVOICELIB := $(CODECDIR)/libwmavoice.a
|
||||||
|
WMAVOICELIB_SRC := $(call preprocess, $(APPSDIR)/codecs/libwmavoice/SOURCES)
|
||||||
|
WMAVOICELIB_OBJ := $(call c2obj, $(WMAVOICELIB_SRC))
|
||||||
|
OTHER_SRC += $(WMAVOICELIB_SRC)
|
||||||
|
|
||||||
|
$(WMAVOICELIB): $(WMAVOICELIB_OBJ)
|
||||||
|
$(SILENT)$(shell rm -f $@)
|
||||||
|
$(call PRINTS,AR $(@F))$(AR) rcs $@ $^ >/dev/null
|
||||||
|
|
||||||
|
WMAVOICEFLAGS = -I$(APPSDIR)/codecs/libwmavoice $(filter-out -O%,$(CODECFLAGS))
|
||||||
|
|
||||||
|
ifeq ($(CPU),coldfire)
|
||||||
|
WMAVOICEFLAGS += -O2
|
||||||
|
else
|
||||||
|
WMAVOICEFLAGS += -O1
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(APP_TYPE),sdl-sim)
|
||||||
|
# wmavoice needs libm in the simulator
|
||||||
|
$(CODECDIR)/wmavoice.codec: $(CODECDIR)/wmavoice.o
|
||||||
|
$(call PRINTS,LD $(@F))$(CC) $(CODECFLAGS) -o $(CODECDIR)/wmavoice.elf \
|
||||||
|
$(filter %.o, $^) \
|
||||||
|
$(filter %.a, $+) \
|
||||||
|
-lgcc -lm $(CODECLDFLAGS)
|
||||||
|
$(SILENT)cp $(CODECDIR)/wmavoice.elf $@
|
||||||
|
endif
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "avcodec.h"
|
#include "wmavoice.h"
|
||||||
#include "get_bits.h"
|
#include "get_bits.h"
|
||||||
#include "put_bits.h"
|
#include "put_bits.h"
|
||||||
#include "wmavoice_data.h"
|
#include "wmavoice_data.h"
|
||||||
|
@ -286,6 +286,10 @@ typedef struct {
|
||||||
*/
|
*/
|
||||||
} WMAVoiceContext;
|
} WMAVoiceContext;
|
||||||
|
|
||||||
|
/* global decode context */
|
||||||
|
static WMAVoiceContext globWMAVoiceCtx;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set up the variable bit mode (VBM) tree from container extradata.
|
* Set up the variable bit mode (VBM) tree from container extradata.
|
||||||
* @param gb bit I/O context.
|
* @param gb bit I/O context.
|
||||||
|
@ -330,9 +334,10 @@ static av_cold int decode_vbmtree(GetBitContext *gb, int8_t vbm_tree[25])
|
||||||
/**
|
/**
|
||||||
* Set up decoder with parameters from demuxer (extradata etc.).
|
* Set up decoder with parameters from demuxer (extradata etc.).
|
||||||
*/
|
*/
|
||||||
static av_cold int wmavoice_decode_init(AVCodecContext *ctx)
|
av_cold int wmavoice_decode_init(AVCodecContext *ctx)
|
||||||
{
|
{
|
||||||
int n, flags, pitch_range, lsp16_flag;
|
int n, flags, pitch_range, lsp16_flag;
|
||||||
|
ctx->priv_data = &globWMAVoiceCtx;
|
||||||
WMAVoiceContext *s = ctx->priv_data;
|
WMAVoiceContext *s = ctx->priv_data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1743,7 +1748,7 @@ static int synth_superframe(AVCodecContext *ctx,
|
||||||
* the wild yet. */
|
* the wild yet. */
|
||||||
if (!get_bits1(gb)) {
|
if (!get_bits1(gb)) {
|
||||||
av_log_missing_feature(ctx, "WMAPro-in-WMAVoice support", 1);
|
av_log_missing_feature(ctx, "WMAPro-in-WMAVoice support", 1);
|
||||||
return -1;
|
return ERROR_WMAPRO_IN_WMAVOICE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (optional) nr. of samples in superframe; always <= 480 and >= 0 */
|
/* (optional) nr. of samples in superframe; always <= 480 and >= 0 */
|
||||||
|
@ -1893,7 +1898,7 @@ static void copy_bits(PutBitContext *pb,
|
||||||
*
|
*
|
||||||
* For more information about frames, see #synth_superframe().
|
* For more information about frames, see #synth_superframe().
|
||||||
*/
|
*/
|
||||||
static int wmavoice_decode_packet(AVCodecContext *ctx, void *data,
|
int wmavoice_decode_packet(AVCodecContext *ctx, void *data,
|
||||||
int *data_size, AVPacket *avpkt)
|
int *data_size, AVPacket *avpkt)
|
||||||
{
|
{
|
||||||
WMAVoiceContext *s = ctx->priv_data;
|
WMAVoiceContext *s = ctx->priv_data;
|
||||||
|
@ -1936,6 +1941,15 @@ static int wmavoice_decode_packet(AVCodecContext *ctx, void *data,
|
||||||
s->sframe_cache_size += s->spillover_nbits;
|
s->sframe_cache_size += s->spillover_nbits;
|
||||||
if ((res = synth_superframe(ctx, data, data_size)) == 0 &&
|
if ((res = synth_superframe(ctx, data, data_size)) == 0 &&
|
||||||
*data_size > 0) {
|
*data_size > 0) {
|
||||||
|
/* convert the float values to int32 for rockbox */
|
||||||
|
int i;
|
||||||
|
int32_t *iptr = data;
|
||||||
|
float *fptr = data;
|
||||||
|
for(i = 0; i < *data_size/sizeof(float); i++)
|
||||||
|
{
|
||||||
|
fptr[i] *= (float)(INT32_MAX);
|
||||||
|
iptr[i] = (int32_t)fptr[i];
|
||||||
|
}
|
||||||
cnt += s->spillover_nbits;
|
cnt += s->spillover_nbits;
|
||||||
s->skip_bits_next = cnt & 7;
|
s->skip_bits_next = cnt & 7;
|
||||||
return cnt >> 3;
|
return cnt >> 3;
|
||||||
|
@ -1957,12 +1971,21 @@ static int wmavoice_decode_packet(AVCodecContext *ctx, void *data,
|
||||||
} else if (*data_size > 0) {
|
} else if (*data_size > 0) {
|
||||||
int cnt = get_bits_count(gb);
|
int cnt = get_bits_count(gb);
|
||||||
s->skip_bits_next = cnt & 7;
|
s->skip_bits_next = cnt & 7;
|
||||||
|
/* convert the float values to int32 for rockbox */
|
||||||
|
int i;
|
||||||
|
int32_t *iptr = data;
|
||||||
|
float *fptr = data;
|
||||||
|
for(i = 0; i < *data_size/sizeof(float); i++)
|
||||||
|
{
|
||||||
|
fptr[i] *= (float)(INT32_MAX);
|
||||||
|
iptr[i] = (int32_t)fptr[i];
|
||||||
|
}
|
||||||
return cnt >> 3;
|
return cnt >> 3;
|
||||||
} else if ((s->sframe_cache_size = pos) > 0) {
|
} else if ((s->sframe_cache_size = pos) > 0) {
|
||||||
/* rewind bit reader to start of last (incomplete) superframe... */
|
/* rewind bit reader to start of last (incomplete) superframe... */
|
||||||
init_get_bits(gb, avpkt->data, size << 3);
|
init_get_bits(gb, avpkt->data, size << 3);
|
||||||
skip_bits_long(gb, (size << 3) - pos);
|
skip_bits_long(gb, (size << 3) - pos);
|
||||||
assert(get_bits_left(gb) == pos);
|
//assert(get_bits_left(gb) == pos);
|
||||||
|
|
||||||
/* ...and cache it for spillover in next packet */
|
/* ...and cache it for spillover in next packet */
|
||||||
init_put_bits(&s->pb, s->sframe_cache, SFRAME_CACHE_MAXSIZE);
|
init_put_bits(&s->pb, s->sframe_cache, SFRAME_CACHE_MAXSIZE);
|
||||||
|
|
7
apps/codecs/libwmavoice/wmavoice.h
Normal file
7
apps/codecs/libwmavoice/wmavoice.h
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#include "avcodec.h"
|
||||||
|
|
||||||
|
#define ERROR_WMAPRO_IN_WMAVOICE -0x162
|
||||||
|
|
||||||
|
av_cold int wmavoice_decode_init(AVCodecContext *ctx);
|
||||||
|
int wmavoice_decode_packet(AVCodecContext *ctx, void *data,
|
||||||
|
int *data_size, AVPacket *avpkt);
|
195
apps/codecs/wmavoice.c
Normal file
195
apps/codecs/wmavoice.c
Normal file
|
@ -0,0 +1,195 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* __________ __ ___.
|
||||||
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||||
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||||
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||||
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||||
|
* \/ \/ \/ \/ \/
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Mohamed Tarek
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "codeclib.h"
|
||||||
|
#include "libasf/asf.h"
|
||||||
|
#include "libwmavoice/wmavoice.h"
|
||||||
|
|
||||||
|
CODEC_HEADER
|
||||||
|
|
||||||
|
static AVCodecContext avctx;
|
||||||
|
static AVPacket avpkt;
|
||||||
|
|
||||||
|
#define MAX_FRAMES 3 /*maximum number of frames per superframe*/
|
||||||
|
#define MAX_FRAMESIZE 160 /* maximum number of samples per frame */
|
||||||
|
#define BUFSIZE MAX_FRAMES*MAX_FRAMESIZE
|
||||||
|
static int32_t decoded[BUFSIZE] IBSS_ATTR;
|
||||||
|
|
||||||
|
|
||||||
|
/* This function initialises AVCodecContext with the data needed for the wmapro
|
||||||
|
* decoder to work. The required data is taken from asf_waveformatex_t because that's
|
||||||
|
* what the rockbox asf metadata parser fill/work with. In the future, when the
|
||||||
|
* codec is being optimised for on-target playback this function should not be needed. */
|
||||||
|
static void init_codec_ctx(AVCodecContext *avctx, asf_waveformatex_t *wfx)
|
||||||
|
{
|
||||||
|
/* Copy the extra-data */
|
||||||
|
avctx->extradata_size = wfx->datalen;
|
||||||
|
avctx->extradata = (uint8_t *)malloc(wfx->datalen*sizeof(uint8_t));
|
||||||
|
memcpy(avctx->extradata, wfx->data, wfx->datalen*sizeof(uint8_t));
|
||||||
|
|
||||||
|
avctx->block_align = wfx->blockalign;
|
||||||
|
avctx->sample_rate = wfx->rate;
|
||||||
|
avctx->channels = wfx->channels;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* this is the codec entry point */
|
||||||
|
enum codec_status codec_main(void)
|
||||||
|
{
|
||||||
|
uint32_t elapsedtime;
|
||||||
|
int retval;
|
||||||
|
asf_waveformatex_t wfx; /* Holds the stream properties */
|
||||||
|
size_t resume_offset;
|
||||||
|
int res; /* Return values from asf_read_packet() and decode_packet() */
|
||||||
|
uint8_t* audiobuf; /* Pointer to the payload of one wma pro packet */
|
||||||
|
int audiobufsize; /* Payload size */
|
||||||
|
int packetlength = 0; /* Logical packet size (minus the header size) */
|
||||||
|
int outlen = 0; /* Number of bytes written to the output buffer */
|
||||||
|
int pktcnt = 0; /* Count of the packets played */
|
||||||
|
|
||||||
|
/* Generic codec initialisation */
|
||||||
|
ci->configure(DSP_SET_SAMPLE_DEPTH, 31);
|
||||||
|
|
||||||
|
|
||||||
|
next_track:
|
||||||
|
|
||||||
|
/* Wait for the metadata to be read */
|
||||||
|
while (!*ci->taginfo_ready && !ci->stop_codec)
|
||||||
|
ci->sleep(1);
|
||||||
|
|
||||||
|
retval = CODEC_OK;
|
||||||
|
|
||||||
|
/* Remember the resume position */
|
||||||
|
resume_offset = ci->id3->offset;
|
||||||
|
restart_track:
|
||||||
|
if (codec_init()) {
|
||||||
|
LOGF("(WMA Voice) Error: Error initialising codec\n");
|
||||||
|
retval = CODEC_ERROR;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy the format metadata we've stored in the id3 TOC field. This
|
||||||
|
saves us from parsing it again here. */
|
||||||
|
memcpy(&wfx, ci->id3->toc, sizeof(wfx));
|
||||||
|
memset(&avctx, 0, sizeof(AVCodecContext));
|
||||||
|
memset(&avpkt, 0, sizeof(AVPacket));
|
||||||
|
|
||||||
|
ci->configure(DSP_SWITCH_FREQUENCY, wfx.rate);
|
||||||
|
ci->configure(DSP_SET_STEREO_MODE, wfx.channels == 1 ?
|
||||||
|
STEREO_MONO : STEREO_INTERLEAVED);
|
||||||
|
codec_set_replaygain(ci->id3);
|
||||||
|
|
||||||
|
/* Initialise the AVCodecContext */
|
||||||
|
init_codec_ctx(&avctx, &wfx);
|
||||||
|
|
||||||
|
if (wmavoice_decode_init(&avctx) < 0) {
|
||||||
|
LOGF("(WMA Voice) Error: Unsupported or corrupt file\n");
|
||||||
|
retval = CODEC_ERROR;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now advance the file position to the first frame */
|
||||||
|
ci->seek_buffer(ci->id3->first_frame_offset);
|
||||||
|
|
||||||
|
elapsedtime = 0;
|
||||||
|
resume_offset = 0;
|
||||||
|
|
||||||
|
/* The main decoding loop */
|
||||||
|
|
||||||
|
while (pktcnt < wfx.numpackets)
|
||||||
|
{
|
||||||
|
ci->yield();
|
||||||
|
if (ci->stop_codec || ci->new_track) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Deal with any pending seek requests */
|
||||||
|
if (ci->seek_time){
|
||||||
|
|
||||||
|
if (ci->seek_time == 1) {
|
||||||
|
ci->seek_complete();
|
||||||
|
goto restart_track; /* Pretend you never saw this... */
|
||||||
|
}
|
||||||
|
|
||||||
|
elapsedtime = asf_seek(ci->seek_time, &wfx);
|
||||||
|
if (elapsedtime < 1){
|
||||||
|
ci->seek_complete();
|
||||||
|
goto next_track;
|
||||||
|
}
|
||||||
|
|
||||||
|
ci->set_elapsed(elapsedtime);
|
||||||
|
ci->seek_complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
new_packet:
|
||||||
|
res = asf_read_packet(&audiobuf, &audiobufsize, &packetlength, &wfx);
|
||||||
|
|
||||||
|
if (res < 0) {
|
||||||
|
LOGF("(WMA Voice) read_packet error %d\n",res);
|
||||||
|
goto done;
|
||||||
|
} else {
|
||||||
|
avpkt.data = audiobuf;
|
||||||
|
avpkt.size = audiobufsize;
|
||||||
|
pktcnt++;
|
||||||
|
|
||||||
|
while(avpkt.size > 0)
|
||||||
|
{
|
||||||
|
/* wmavoice_decode_packet checks for the output buffer size to
|
||||||
|
avoid overflows */
|
||||||
|
outlen = BUFSIZE*sizeof(int32_t);
|
||||||
|
|
||||||
|
res = wmavoice_decode_packet(&avctx, decoded, &outlen, &avpkt);
|
||||||
|
if(res < 0) {
|
||||||
|
LOGF("(WMA Voice) Error: decode_packet returned %d", res);
|
||||||
|
if(res == ERROR_WMAPRO_IN_WMAVOICE){
|
||||||
|
/* Just skip this packet */
|
||||||
|
ci->advance_buffer(packetlength);
|
||||||
|
goto new_packet;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
avpkt.data += res;
|
||||||
|
avpkt.size -= res;
|
||||||
|
if(outlen) {
|
||||||
|
ci->yield ();
|
||||||
|
outlen /= sizeof(int32_t);
|
||||||
|
ci->pcmbuf_insert(decoded, NULL, outlen);
|
||||||
|
elapsedtime += outlen*10/(wfx.rate/100);
|
||||||
|
ci->set_elapsed(elapsedtime);
|
||||||
|
ci->yield ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Advance to the next logical packet */
|
||||||
|
ci->advance_buffer(packetlength);
|
||||||
|
}
|
||||||
|
retval = CODEC_OK;
|
||||||
|
|
||||||
|
done:
|
||||||
|
if (ci->request_next_track())
|
||||||
|
goto next_track;
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
|
@ -182,6 +182,9 @@ const struct afmt_entry audio_formats[AFMT_NUM_CODECS] =
|
||||||
/* True Audio */
|
/* True Audio */
|
||||||
[AFMT_TTA] =
|
[AFMT_TTA] =
|
||||||
AFMT_ENTRY("TTA", "tta", NULL, "tta\0" ),
|
AFMT_ENTRY("TTA", "tta", NULL, "tta\0" ),
|
||||||
|
/* WMA Voice in ASF */
|
||||||
|
[AFMT_WMAVOICE] =
|
||||||
|
AFMT_ENTRY("WMAVoice", "wmavoice", NULL, "wma\0wmv\0asf\0" ),
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -297,7 +300,7 @@ bool get_metadata(struct mp3entry* id3, int fd, const char* trackname)
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AFMT_WMA:
|
case AFMT_WMA:
|
||||||
if (!get_asf_metadata(fd, id3))
|
if (!get_asf_metadata(fd, id3))
|
||||||
{
|
{
|
||||||
|
|
|
@ -84,6 +84,7 @@ enum
|
||||||
AFMT_VOX, /* VOX */
|
AFMT_VOX, /* VOX */
|
||||||
AFMT_WAVE64, /* Wave64 */
|
AFMT_WAVE64, /* Wave64 */
|
||||||
AFMT_TTA, /* True Audio */
|
AFMT_TTA, /* True Audio */
|
||||||
|
AFMT_WMAVOICE, /* WMA Voice in ASF */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* add new formats at any index above this line to have a sensible order -
|
/* add new formats at any index above this line to have a sensible order -
|
||||||
|
|
|
@ -357,6 +357,11 @@ static int asf_parse_header(int fd, struct mp3entry* id3,
|
||||||
wfx->audiostream = flags&0x7f;
|
wfx->audiostream = flags&0x7f;
|
||||||
/* Correct codectype to redirect playback to the proper .codec */
|
/* Correct codectype to redirect playback to the proper .codec */
|
||||||
id3->codectype = AFMT_WMAPRO;
|
id3->codectype = AFMT_WMAPRO;
|
||||||
|
} else if (wfx->codec_id == ASF_CODEC_ID_WMAVOICE) {
|
||||||
|
read(fd, wfx->data, wfx->datalen);
|
||||||
|
lseek(fd,current.size - 24 - 72 - wfx->datalen,SEEK_CUR);
|
||||||
|
wfx->audiostream = flags&0x7f;
|
||||||
|
id3->codectype = AFMT_WMAVOICE;
|
||||||
} else {
|
} else {
|
||||||
DEBUGF("Unsupported WMA codec (Lossless, Voice, etc)\n");
|
DEBUGF("Unsupported WMA codec (Lossless, Voice, etc)\n");
|
||||||
lseek(fd,current.size - 24 - 72,SEEK_CUR);
|
lseek(fd,current.size - 24 - 72,SEEK_CUR);
|
||||||
|
|
Loading…
Reference in a new issue