summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/codecs/libasf/asf.h3
-rw-r--r--apps/codecs/libwmavoice/SOURCES17
-rw-r--r--apps/codecs/libwmavoice/libwmavoice.make37
-rw-r--r--apps/codecs/libwmavoice/wmavoice.c33
-rw-r--r--apps/codecs/libwmavoice/wmavoice.h7
-rw-r--r--apps/codecs/wmavoice.c195
-rw-r--r--apps/metadata.c5
-rw-r--r--apps/metadata.h1
-rw-r--r--apps/metadata/asf.c5
9 files changed, 296 insertions, 7 deletions
diff --git a/apps/codecs/libasf/asf.h b/apps/codecs/libasf/asf.h
index b0adb7dfc7..a7d384cf3d 100644
--- a/apps/codecs/libasf/asf.h
+++ b/apps/codecs/libasf/asf.h
@@ -7,6 +7,7 @@
7#define ASF_CODEC_ID_WMAV1 0x160 7#define ASF_CODEC_ID_WMAV1 0x160
8#define ASF_CODEC_ID_WMAV2 0x161 8#define ASF_CODEC_ID_WMAV2 0x161
9#define ASF_CODEC_ID_WMAPRO 0x162 9#define ASF_CODEC_ID_WMAPRO 0x162
10#define ASF_CODEC_ID_WMAVOICE 0x00A
10 11
11enum asf_error_e { 12enum asf_error_e {
12 ASF_ERROR_INTERNAL = -1, /* incorrect input to API calls */ 13 ASF_ERROR_INTERNAL = -1, /* incorrect input to API calls */
@@ -33,7 +34,7 @@ struct asf_waveformatex_s {
33 uint16_t bitspersample; 34 uint16_t bitspersample;
34 uint16_t datalen; 35 uint16_t datalen;
35 uint16_t numpackets; 36 uint16_t numpackets;
36 uint8_t data[18]; 37 uint8_t data[46];
37}; 38};
38typedef struct asf_waveformatex_s asf_waveformatex_t; 39typedef struct asf_waveformatex_s asf_waveformatex_t;
39 40
diff --git a/apps/codecs/libwmavoice/SOURCES b/apps/codecs/libwmavoice/SOURCES
new file mode 100644
index 0000000000..c98821c42a
--- /dev/null
+++ b/apps/codecs/libwmavoice/SOURCES
@@ -0,0 +1,17 @@
1acelp_filters.c
2acelp_vectors.c
3avfft.c
4bitstream.c
5celp_filters.c
6celp_math.c
7dct.c
8fft.c
9lsp.c
10mdct.c
11rdft.c
12utils.c
13wmavoice.c
14libavutil/log.c
15libavutil/lzo.c
16libavutil/mem.c
17libavutil/mathematics.c
diff --git a/apps/codecs/libwmavoice/libwmavoice.make b/apps/codecs/libwmavoice/libwmavoice.make
new file mode 100644
index 0000000000..0497e18e1b
--- /dev/null
+++ b/apps/codecs/libwmavoice/libwmavoice.make
@@ -0,0 +1,37 @@
1# __________ __ ___.
2# Open \______ \ ____ ____ | | _\_ |__ _______ ___
3# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
4# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
5# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
6# \/ \/ \/ \/ \/
7# $Id: libwmavoice.make 27586 2010-07-27 06:48:15Z nls $
8#
9
10# libwmavoice
11WMAVOICELIB := $(CODECDIR)/libwmavoice.a
12WMAVOICELIB_SRC := $(call preprocess, $(APPSDIR)/codecs/libwmavoice/SOURCES)
13WMAVOICELIB_OBJ := $(call c2obj, $(WMAVOICELIB_SRC))
14OTHER_SRC += $(WMAVOICELIB_SRC)
15
16$(WMAVOICELIB): $(WMAVOICELIB_OBJ)
17 $(SILENT)$(shell rm -f $@)
18 $(call PRINTS,AR $(@F))$(AR) rcs $@ $^ >/dev/null
19
20WMAVOICEFLAGS = -I$(APPSDIR)/codecs/libwmavoice $(filter-out -O%,$(CODECFLAGS))
21
22ifeq ($(CPU),coldfire)
23 WMAVOICEFLAGS += -O2
24else
25 WMAVOICEFLAGS += -O1
26endif
27
28ifeq ($(APP_TYPE),sdl-sim)
29# wmavoice needs libm in the simulator
30$(CODECDIR)/wmavoice.codec: $(CODECDIR)/wmavoice.o
31 $(call PRINTS,LD $(@F))$(CC) $(CODECFLAGS) -o $(CODECDIR)/wmavoice.elf \
32 $(filter %.o, $^) \
33 $(filter %.a, $+) \
34 -lgcc -lm $(CODECLDFLAGS)
35 $(SILENT)cp $(CODECDIR)/wmavoice.elf $@
36endif
37
diff --git a/apps/codecs/libwmavoice/wmavoice.c b/apps/codecs/libwmavoice/wmavoice.c
index 39bcb0e04e..f8bd6d656e 100644
--- a/apps/codecs/libwmavoice/wmavoice.c
+++ b/apps/codecs/libwmavoice/wmavoice.c
@@ -26,7 +26,7 @@
26 */ 26 */
27 27
28#include <math.h> 28#include <math.h>
29#include "avcodec.h" 29#include "wmavoice.h"
30#include "get_bits.h" 30#include "get_bits.h"
31#include "put_bits.h" 31#include "put_bits.h"
32#include "wmavoice_data.h" 32#include "wmavoice_data.h"
@@ -286,6 +286,10 @@ typedef struct {
286 */ 286 */
287} WMAVoiceContext; 287} WMAVoiceContext;
288 288
289/* global decode context */
290static WMAVoiceContext globWMAVoiceCtx;
291
292
289/** 293/**
290 * Set up the variable bit mode (VBM) tree from container extradata. 294 * Set up the variable bit mode (VBM) tree from container extradata.
291 * @param gb bit I/O context. 295 * @param gb bit I/O context.
@@ -330,9 +334,10 @@ static av_cold int decode_vbmtree(GetBitContext *gb, int8_t vbm_tree[25])
330/** 334/**
331 * Set up decoder with parameters from demuxer (extradata etc.). 335 * Set up decoder with parameters from demuxer (extradata etc.).
332 */ 336 */
333static av_cold int wmavoice_decode_init(AVCodecContext *ctx) 337av_cold int wmavoice_decode_init(AVCodecContext *ctx)
334{ 338{
335 int n, flags, pitch_range, lsp16_flag; 339 int n, flags, pitch_range, lsp16_flag;
340 ctx->priv_data = &globWMAVoiceCtx;
336 WMAVoiceContext *s = ctx->priv_data; 341 WMAVoiceContext *s = ctx->priv_data;
337 342
338 /** 343 /**
@@ -1743,7 +1748,7 @@ static int synth_superframe(AVCodecContext *ctx,
1743 * the wild yet. */ 1748 * the wild yet. */
1744 if (!get_bits1(gb)) { 1749 if (!get_bits1(gb)) {
1745 av_log_missing_feature(ctx, "WMAPro-in-WMAVoice support", 1); 1750 av_log_missing_feature(ctx, "WMAPro-in-WMAVoice support", 1);
1746 return -1; 1751 return ERROR_WMAPRO_IN_WMAVOICE;
1747 } 1752 }
1748 1753
1749 /* (optional) nr. of samples in superframe; always <= 480 and >= 0 */ 1754 /* (optional) nr. of samples in superframe; always <= 480 and >= 0 */
@@ -1893,7 +1898,7 @@ static void copy_bits(PutBitContext *pb,
1893 * 1898 *
1894 * For more information about frames, see #synth_superframe(). 1899 * For more information about frames, see #synth_superframe().
1895 */ 1900 */
1896static int wmavoice_decode_packet(AVCodecContext *ctx, void *data, 1901int wmavoice_decode_packet(AVCodecContext *ctx, void *data,
1897 int *data_size, AVPacket *avpkt) 1902 int *data_size, AVPacket *avpkt)
1898{ 1903{
1899 WMAVoiceContext *s = ctx->priv_data; 1904 WMAVoiceContext *s = ctx->priv_data;
@@ -1936,6 +1941,15 @@ static int wmavoice_decode_packet(AVCodecContext *ctx, void *data,
1936 s->sframe_cache_size += s->spillover_nbits; 1941 s->sframe_cache_size += s->spillover_nbits;
1937 if ((res = synth_superframe(ctx, data, data_size)) == 0 && 1942 if ((res = synth_superframe(ctx, data, data_size)) == 0 &&
1938 *data_size > 0) { 1943 *data_size > 0) {
1944 /* convert the float values to int32 for rockbox */
1945 int i;
1946 int32_t *iptr = data;
1947 float *fptr = data;
1948 for(i = 0; i < *data_size/sizeof(float); i++)
1949 {
1950 fptr[i] *= (float)(INT32_MAX);
1951 iptr[i] = (int32_t)fptr[i];
1952 }
1939 cnt += s->spillover_nbits; 1953 cnt += s->spillover_nbits;
1940 s->skip_bits_next = cnt & 7; 1954 s->skip_bits_next = cnt & 7;
1941 return cnt >> 3; 1955 return cnt >> 3;
@@ -1957,12 +1971,21 @@ static int wmavoice_decode_packet(AVCodecContext *ctx, void *data,
1957 } else if (*data_size > 0) { 1971 } else if (*data_size > 0) {
1958 int cnt = get_bits_count(gb); 1972 int cnt = get_bits_count(gb);
1959 s->skip_bits_next = cnt & 7; 1973 s->skip_bits_next = cnt & 7;
1974 /* convert the float values to int32 for rockbox */
1975 int i;
1976 int32_t *iptr = data;
1977 float *fptr = data;
1978 for(i = 0; i < *data_size/sizeof(float); i++)
1979 {
1980 fptr[i] *= (float)(INT32_MAX);
1981 iptr[i] = (int32_t)fptr[i];
1982 }
1960 return cnt >> 3; 1983 return cnt >> 3;
1961 } else if ((s->sframe_cache_size = pos) > 0) { 1984 } else if ((s->sframe_cache_size = pos) > 0) {
1962 /* rewind bit reader to start of last (incomplete) superframe... */ 1985 /* rewind bit reader to start of last (incomplete) superframe... */
1963 init_get_bits(gb, avpkt->data, size << 3); 1986 init_get_bits(gb, avpkt->data, size << 3);
1964 skip_bits_long(gb, (size << 3) - pos); 1987 skip_bits_long(gb, (size << 3) - pos);
1965 assert(get_bits_left(gb) == pos); 1988 //assert(get_bits_left(gb) == pos);
1966 1989
1967 /* ...and cache it for spillover in next packet */ 1990 /* ...and cache it for spillover in next packet */
1968 init_put_bits(&s->pb, s->sframe_cache, SFRAME_CACHE_MAXSIZE); 1991 init_put_bits(&s->pb, s->sframe_cache, SFRAME_CACHE_MAXSIZE);
diff --git a/apps/codecs/libwmavoice/wmavoice.h b/apps/codecs/libwmavoice/wmavoice.h
new file mode 100644
index 0000000000..33ec72b4e2
--- /dev/null
+++ b/apps/codecs/libwmavoice/wmavoice.h
@@ -0,0 +1,7 @@
1#include "avcodec.h"
2
3#define ERROR_WMAPRO_IN_WMAVOICE -0x162
4
5av_cold int wmavoice_decode_init(AVCodecContext *ctx);
6int wmavoice_decode_packet(AVCodecContext *ctx, void *data,
7 int *data_size, AVPacket *avpkt);
diff --git a/apps/codecs/wmavoice.c b/apps/codecs/wmavoice.c
new file mode 100644
index 0000000000..904af23b99
--- /dev/null
+++ b/apps/codecs/wmavoice.c
@@ -0,0 +1,195 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2010 Mohamed Tarek
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "codeclib.h"
23#include "libasf/asf.h"
24#include "libwmavoice/wmavoice.h"
25
26CODEC_HEADER
27
28static AVCodecContext avctx;
29static AVPacket avpkt;
30
31#define MAX_FRAMES 3 /*maximum number of frames per superframe*/
32#define MAX_FRAMESIZE 160 /* maximum number of samples per frame */
33#define BUFSIZE MAX_FRAMES*MAX_FRAMESIZE
34static int32_t decoded[BUFSIZE] IBSS_ATTR;
35
36
37/* This function initialises AVCodecContext with the data needed for the wmapro
38 * decoder to work. The required data is taken from asf_waveformatex_t because that's
39 * what the rockbox asf metadata parser fill/work with. In the future, when the
40 * codec is being optimised for on-target playback this function should not be needed. */
41static void init_codec_ctx(AVCodecContext *avctx, asf_waveformatex_t *wfx)
42{
43 /* Copy the extra-data */
44 avctx->extradata_size = wfx->datalen;
45 avctx->extradata = (uint8_t *)malloc(wfx->datalen*sizeof(uint8_t));
46 memcpy(avctx->extradata, wfx->data, wfx->datalen*sizeof(uint8_t));
47
48 avctx->block_align = wfx->blockalign;
49 avctx->sample_rate = wfx->rate;
50 avctx->channels = wfx->channels;
51
52}
53
54/* this is the codec entry point */
55enum codec_status codec_main(void)
56{
57 uint32_t elapsedtime;
58 int retval;
59 asf_waveformatex_t wfx; /* Holds the stream properties */
60 size_t resume_offset;
61 int res; /* Return values from asf_read_packet() and decode_packet() */
62 uint8_t* audiobuf; /* Pointer to the payload of one wma pro packet */
63 int audiobufsize; /* Payload size */
64 int packetlength = 0; /* Logical packet size (minus the header size) */
65 int outlen = 0; /* Number of bytes written to the output buffer */
66 int pktcnt = 0; /* Count of the packets played */
67
68 /* Generic codec initialisation */
69 ci->configure(DSP_SET_SAMPLE_DEPTH, 31);
70
71
72next_track:
73
74 /* Wait for the metadata to be read */
75 while (!*ci->taginfo_ready && !ci->stop_codec)
76 ci->sleep(1);
77
78 retval = CODEC_OK;
79
80 /* Remember the resume position */
81 resume_offset = ci->id3->offset;
82 restart_track:
83 if (codec_init()) {
84 LOGF("(WMA Voice) Error: Error initialising codec\n");
85 retval = CODEC_ERROR;
86 goto done;
87 }
88
89 /* Copy the format metadata we've stored in the id3 TOC field. This
90 saves us from parsing it again here. */
91 memcpy(&wfx, ci->id3->toc, sizeof(wfx));
92 memset(&avctx, 0, sizeof(AVCodecContext));
93 memset(&avpkt, 0, sizeof(AVPacket));
94
95 ci->configure(DSP_SWITCH_FREQUENCY, wfx.rate);
96 ci->configure(DSP_SET_STEREO_MODE, wfx.channels == 1 ?
97 STEREO_MONO : STEREO_INTERLEAVED);
98 codec_set_replaygain(ci->id3);
99
100 /* Initialise the AVCodecContext */
101 init_codec_ctx(&avctx, &wfx);
102
103 if (wmavoice_decode_init(&avctx) < 0) {
104 LOGF("(WMA Voice) Error: Unsupported or corrupt file\n");
105 retval = CODEC_ERROR;
106 goto done;
107 }
108
109 /* Now advance the file position to the first frame */
110 ci->seek_buffer(ci->id3->first_frame_offset);
111
112 elapsedtime = 0;
113 resume_offset = 0;
114
115 /* The main decoding loop */
116
117 while (pktcnt < wfx.numpackets)
118 {
119 ci->yield();
120 if (ci->stop_codec || ci->new_track) {
121 goto done;
122 }
123
124 /* Deal with any pending seek requests */
125 if (ci->seek_time){
126
127 if (ci->seek_time == 1) {
128 ci->seek_complete();
129 goto restart_track; /* Pretend you never saw this... */
130 }
131
132 elapsedtime = asf_seek(ci->seek_time, &wfx);
133 if (elapsedtime < 1){
134 ci->seek_complete();
135 goto next_track;
136 }
137
138 ci->set_elapsed(elapsedtime);
139 ci->seek_complete();
140 }
141
142new_packet:
143 res = asf_read_packet(&audiobuf, &audiobufsize, &packetlength, &wfx);
144
145 if (res < 0) {
146 LOGF("(WMA Voice) read_packet error %d\n",res);
147 goto done;
148 } else {
149 avpkt.data = audiobuf;
150 avpkt.size = audiobufsize;
151 pktcnt++;
152
153 while(avpkt.size > 0)
154 {
155 /* wmavoice_decode_packet checks for the output buffer size to
156 avoid overflows */
157 outlen = BUFSIZE*sizeof(int32_t);
158
159 res = wmavoice_decode_packet(&avctx, decoded, &outlen, &avpkt);
160 if(res < 0) {
161 LOGF("(WMA Voice) Error: decode_packet returned %d", res);
162 if(res == ERROR_WMAPRO_IN_WMAVOICE){
163 /* Just skip this packet */
164 ci->advance_buffer(packetlength);
165 goto new_packet;
166 }
167 else
168 goto done;
169 }
170 avpkt.data += res;
171 avpkt.size -= res;
172 if(outlen) {
173 ci->yield ();
174 outlen /= sizeof(int32_t);
175 ci->pcmbuf_insert(decoded, NULL, outlen);
176 elapsedtime += outlen*10/(wfx.rate/100);
177 ci->set_elapsed(elapsedtime);
178 ci->yield ();
179 }
180 }
181
182 }
183
184 /* Advance to the next logical packet */
185 ci->advance_buffer(packetlength);
186 }
187 retval = CODEC_OK;
188
189done:
190 if (ci->request_next_track())
191 goto next_track;
192
193 return retval;
194}
195
diff --git a/apps/metadata.c b/apps/metadata.c
index 076b753958..15b7d9f72b 100644
--- a/apps/metadata.c
+++ b/apps/metadata.c
@@ -182,6 +182,9 @@ const struct afmt_entry audio_formats[AFMT_NUM_CODECS] =
182 /* True Audio */ 182 /* True Audio */
183 [AFMT_TTA] = 183 [AFMT_TTA] =
184 AFMT_ENTRY("TTA", "tta", NULL, "tta\0" ), 184 AFMT_ENTRY("TTA", "tta", NULL, "tta\0" ),
185 /* WMA Voice in ASF */
186 [AFMT_WMAVOICE] =
187 AFMT_ENTRY("WMAVoice", "wmavoice", NULL, "wma\0wmv\0asf\0" ),
185#endif 188#endif
186}; 189};
187 190
@@ -297,7 +300,7 @@ bool get_metadata(struct mp3entry* id3, int fd, const char* trackname)
297 } 300 }
298 301
299 break; 302 break;
300 303
301 case AFMT_WMA: 304 case AFMT_WMA:
302 if (!get_asf_metadata(fd, id3)) 305 if (!get_asf_metadata(fd, id3))
303 { 306 {
diff --git a/apps/metadata.h b/apps/metadata.h
index 6b15f6dead..b73d92b83f 100644
--- a/apps/metadata.h
+++ b/apps/metadata.h
@@ -84,6 +84,7 @@ enum
84 AFMT_VOX, /* VOX */ 84 AFMT_VOX, /* VOX */
85 AFMT_WAVE64, /* Wave64 */ 85 AFMT_WAVE64, /* Wave64 */
86 AFMT_TTA, /* True Audio */ 86 AFMT_TTA, /* True Audio */
87 AFMT_WMAVOICE, /* WMA Voice in ASF */
87#endif 88#endif
88 89
89 /* add new formats at any index above this line to have a sensible order - 90 /* add new formats at any index above this line to have a sensible order -
diff --git a/apps/metadata/asf.c b/apps/metadata/asf.c
index ba1b8972af..c445e485a2 100644
--- a/apps/metadata/asf.c
+++ b/apps/metadata/asf.c
@@ -357,6 +357,11 @@ static int asf_parse_header(int fd, struct mp3entry* id3,
357 wfx->audiostream = flags&0x7f; 357 wfx->audiostream = flags&0x7f;
358 /* Correct codectype to redirect playback to the proper .codec */ 358 /* Correct codectype to redirect playback to the proper .codec */
359 id3->codectype = AFMT_WMAPRO; 359 id3->codectype = AFMT_WMAPRO;
360 } else if (wfx->codec_id == ASF_CODEC_ID_WMAVOICE) {
361 read(fd, wfx->data, wfx->datalen);
362 lseek(fd,current.size - 24 - 72 - wfx->datalen,SEEK_CUR);
363 wfx->audiostream = flags&0x7f;
364 id3->codectype = AFMT_WMAVOICE;
360 } else { 365 } else {
361 DEBUGF("Unsupported WMA codec (Lossless, Voice, etc)\n"); 366 DEBUGF("Unsupported WMA codec (Lossless, Voice, etc)\n");
362 lseek(fd,current.size - 24 - 72,SEEK_CUR); 367 lseek(fd,current.size - 24 - 72,SEEK_CUR);