summaryrefslogtreecommitdiff
path: root/apps/codecs
diff options
context:
space:
mode:
Diffstat (limited to 'apps/codecs')
-rw-r--r--apps/codecs/libwavpack/bits.c22
-rw-r--r--apps/codecs/mp3_enc.c1182
-rw-r--r--apps/codecs/wav_enc.c419
-rw-r--r--apps/codecs/wavpack_enc.c539
4 files changed, 1461 insertions, 701 deletions
diff --git a/apps/codecs/libwavpack/bits.c b/apps/codecs/libwavpack/bits.c
index 0a148e1..0f0e79c 100644
--- a/apps/codecs/libwavpack/bits.c
+++ b/apps/codecs/libwavpack/bits.c
@@ -15,6 +15,7 @@
// the malloc() system is provided.
#include "wavpack.h"
+#include "system.h"
#include <string.h>
@@ -118,19 +119,16 @@ uint32_t bs_close_write (Bitstream *bs)
void little_endian_to_native (void *data, char *format)
{
uchar *cp = (uchar *) data;
- int32_t temp;
while (*format) {
switch (*format) {
case 'L':
- temp = cp [0] + ((int32_t) cp [1] << 8) + ((int32_t) cp [2] << 16) + ((int32_t) cp [3] << 24);
- * (int32_t *) cp = temp;
+ *(long *)cp = letoh32(*(long *)cp);
cp += 4;
break;
case 'S':
- temp = cp [0] + (cp [1] << 8);
- * (short *) cp = (short) temp;
+ *(short *)cp = letoh16(*(short *)cp);
cp += 2;
break;
@@ -148,28 +146,22 @@ void little_endian_to_native (void *data, char *format)
void native_to_little_endian (void *data, char *format)
{
uchar *cp = (uchar *) data;
- int32_t temp;
while (*format) {
switch (*format) {
case 'L':
- temp = * (int32_t *) cp;
- *cp++ = (uchar) temp;
- *cp++ = (uchar) (temp >> 8);
- *cp++ = (uchar) (temp >> 16);
- *cp++ = (uchar) (temp >> 24);
+ *(long *)cp = htole32(*(long *)cp);
+ cp += 4;
break;
case 'S':
- temp = * (short *) cp;
- *cp++ = (uchar) temp;
- *cp++ = (uchar) (temp >> 8);
+ *(short *)cp = htole16(*(short *)cp);
+ cp += 2;
break;
default:
if (*format >= '0' && *format <= '9')
cp += *format - '0';
-
break;
}
diff --git a/apps/codecs/mp3_enc.c b/apps/codecs/mp3_enc.c
index 3caca94..cb727ce 100644
--- a/apps/codecs/mp3_enc.c
+++ b/apps/codecs/mp3_enc.c
@@ -32,20 +32,19 @@
#ifndef SIMULATOR
+#include <inttypes.h>
#include "codeclib.h"
-CODEC_HEADER
+CODEC_ENC_HEADER
-#ifdef USE_IRAM
-extern char iramcopy[];
-extern char iramstart[];
-extern char iramend[];
-extern char iedata[];
-extern char iend[];
-#endif
-
-
-#define SAMP_PER_FRAME 1152
+#define ENC_PADDING_FRAMES1 2
+#define ENC_PADDING_FRAMES2 4
+#define ENC_DELAY_SAMP 576
+#define ENC_DELAY_SIZE (ENC_DELAY_SAMP*4)
+#define SAMP_PER_FRAME1 1152
+#define SAMP_PER_FRAME2 576
+#define PCM_CHUNK_SIZE1 (SAMP_PER_FRAME1*4)
+#define PCM_CHUNK_SIZE2 (SAMP_PER_FRAME2*4)
#define SAMPL2 576
#define SBLIMIT 32
#define HTN 16
@@ -54,15 +53,16 @@ extern char iend[];
#define putlong(c, s) if(s+sz <= 32) { cc = (cc << s) | c; sz+= s; } \
else { putbits(cc, sz); cc = c; sz = s; }
-enum e_byte_order { order_unknown, order_bigEndian, order_littleEndian };
-
-typedef unsigned long uint32;
-typedef unsigned short uint16;
-typedef unsigned char uint8;
-
+#ifdef USE_IRAM
+extern char iramcopy[];
+extern char iramstart[];
+extern char iramend[];
+extern char iedata[];
+extern char iend[];
+#endif
typedef struct {
- int type; /* 0=(22.05,24,16kHz) 1=(44.1,48,32kHz) */
+ int type; /* 0=(MPEG2 - 22.05,24,16kHz) 1=(MPEG1 - 44.1,48,32kHz) */
int mode; /* 0=stereo, 1=jstereo, 2=dual, 3=mono */
int bitrate;
int padding;
@@ -73,21 +73,20 @@ typedef struct {
/* Side information */
typedef struct {
- uint32 part2_3_length;
+ uint32_t part2_3_length;
int count1; /* number of 0-1-quadruples */
- uint32 global_gain;
- uint32 table_select[4];
- uint32 region_0_1;
- uint32 address1;
- uint32 address2;
- uint32 address3;
+ uint32_t global_gain;
+ uint32_t table_select[4];
+ uint32_t region_0_1;
+ uint32_t address1;
+ uint32_t address2;
+ uint32_t address3;
long quantStep;
long additStep;
long max_val;
} side_info_t;
typedef struct {
- enum e_byte_order byte_order;
side_info_t cod_info[2][2];
mpeg_t mpg;
long frac_per_frame;
@@ -98,19 +97,18 @@ typedef struct {
int ResvSize;
int channels;
int granules;
- int resample;
long samplerate;
} config_t;
typedef struct {
int bitpos; /* current bitpos for writing */
- uint32 bbuf[263];
+ uint32_t bbuf[263];
} BF_Data;
struct huffcodetab {
int len; /* max. index */
- const uint8 *table; /* pointer to array[len][len] */
- const uint8 *hlen; /* pointer to array[len][len] */
+ const uint8_t *table; /* pointer to array[len][len] */
+ const uint8_t *hlen; /* pointer to array[len][len] */
};
struct huffcodebig {
@@ -127,102 +125,105 @@ struct huffcodebig {
#define shft_n(x,n) ((x) >> n)
#define SQRT 724 /* sqrt(2) * 512 */
-short mfbuf [2*(1152+512)] IBSS_ATTR; /* 3328 Bytes */
-int sb_data [2][2][18][SBLIMIT] IBSS_ATTR; /* 13824 Bytes */
-int mdct_freq [SAMPL2] IBSS_ATTR; /* 9216 Bytes */
-short enc_data [SAMPL2] IBSS_ATTR; /* 4608 Bytes */
-uint32 scalefac [23] IBSS_ATTR; /* 92 Bytes */
-BF_Data CodedData IBSS_ATTR; /* 1056 Bytes */
-int ca [8] IBSS_ATTR; /* 32 Bytes */
-int cs [8] IBSS_ATTR; /* 32 Bytes */
-int cx [9] IBSS_ATTR; /* 36 Bytes */
-int win [18][4] IBSS_ATTR; /* 288 Bytes */
-short enwindow [15*27+24] IBSS_ATTR; /* 862 Bytes */
-short int2idx [4096] IBSS_ATTR; /* 8192 Bytes */
-uint8 ht_count [2][2][16] IBSS_ATTR; /* 64 Bytes */
-uint32 tab01 [ 16] IBSS_ATTR; /* 64 Bytes */
-uint32 tab23 [ 9] IBSS_ATTR; /* 36 Bytes */
-uint32 tab56 [ 16] IBSS_ATTR; /* 64 Bytes */
-uint32 tab1315 [256] IBSS_ATTR; /* 1024 Bytes */
-uint32 tab1624 [256] IBSS_ATTR; /* 1024 Bytes */
-uint32 tab789 [ 36] IBSS_ATTR; /* 144 Bytes */
-uint32 tabABC [ 64] IBSS_ATTR; /* 256 Bytes */
-uint8 t1HB [ 4] IBSS_ATTR;
-uint8 t2HB [ 9] IBSS_ATTR;
-uint8 t3HB [ 9] IBSS_ATTR;
-uint8 t5HB [ 16] IBSS_ATTR;
-uint8 t6HB [ 16] IBSS_ATTR;
-uint8 t7HB [ 36] IBSS_ATTR;
-uint8 t8HB [ 36] IBSS_ATTR;
-uint8 t9HB [ 36] IBSS_ATTR;
-uint8 t10HB [ 64] IBSS_ATTR;
-uint8 t11HB [ 64] IBSS_ATTR;
-uint8 t12HB [ 64] IBSS_ATTR;
-uint8 t13HB [256] IBSS_ATTR;
-uint8 t15HB [256] IBSS_ATTR;
-uint16 t16HB [256] IBSS_ATTR;
-uint16 t24HB [256] IBSS_ATTR;
-uint8 t1l [ 8] IBSS_ATTR;
-uint8 t2l [ 9] IBSS_ATTR;
-uint8 t3l [ 9] IBSS_ATTR;
-uint8 t5l [ 16] IBSS_ATTR;
-uint8 t6l [ 16] IBSS_ATTR;
-uint8 t7l [ 36] IBSS_ATTR;
-uint8 t8l [ 36] IBSS_ATTR;
-uint8 t9l [ 36] IBSS_ATTR;
-uint8 t10l [ 64] IBSS_ATTR;
-uint8 t11l [ 64] IBSS_ATTR;
-uint8 t12l [ 64] IBSS_ATTR;
-uint8 t13l [256] IBSS_ATTR;
-uint8 t15l [256] IBSS_ATTR;
-uint8 t16l [256] IBSS_ATTR;
-uint8 t24l [256] IBSS_ATTR;
-struct huffcodetab ht [HTN] IBSS_ATTR;
-
-static config_t cfg;
+static short mfbuf [2*(1152+512)] IBSS_ATTR; /* 3328 Bytes */
+static int sb_data [2][2][18][SBLIMIT] IBSS_ATTR; /* 13824 Bytes */
+static int mdct_freq [SAMPL2] IBSS_ATTR; /* 9216 Bytes */
+static short enc_data [SAMPL2] IBSS_ATTR; /* 4608 Bytes */
+static uint32_t scalefac [23] IBSS_ATTR; /* 92 Bytes */
+static BF_Data CodedData IBSS_ATTR; /* 1056 Bytes */
+static int ca [8] IBSS_ATTR; /* 32 Bytes */
+static int cs [8] IBSS_ATTR; /* 32 Bytes */
+static int cx [9] IBSS_ATTR; /* 36 Bytes */
+static int win [18][4] IBSS_ATTR; /* 288 Bytes */
+static short enwindow [15*27+24] IBSS_ATTR; /* 862 Bytes */
+static short int2idx [4096] IBSS_ATTR; /* 8192 Bytes */
+static uint8_t ht_count [2][2][16] IBSS_ATTR; /* 64 Bytes */
+static uint32_t tab01 [ 16] IBSS_ATTR; /* 64 Bytes */
+static uint32_t tab23 [ 9] IBSS_ATTR; /* 36 Bytes */
+static uint32_t tab56 [ 16] IBSS_ATTR; /* 64 Bytes */
+static uint32_t tab1315 [256] IBSS_ATTR; /* 1024 Bytes */
+static uint32_t tab1624 [256] IBSS_ATTR; /* 1024 Bytes */
+static uint32_t tab789 [ 36] IBSS_ATTR; /* 144 Bytes */
+static uint32_t tabABC [ 64] IBSS_ATTR; /* 256 Bytes */
+static uint8_t t1HB [ 4] IBSS_ATTR;
+static uint8_t t2HB [ 9] IBSS_ATTR;
+static uint8_t t3HB [ 9] IBSS_ATTR;
+static uint8_t t5HB [ 16] IBSS_ATTR;
+static uint8_t t6HB [ 16] IBSS_ATTR;
+static uint8_t t7HB [ 36] IBSS_ATTR;
+static uint8_t t8HB [ 36] IBSS_ATTR;
+static uint8_t t9HB [ 36] IBSS_ATTR;
+static uint8_t t10HB [ 64] IBSS_ATTR;
+static uint8_t t11HB [ 64] IBSS_ATTR;
+static uint8_t t12HB [ 64] IBSS_ATTR;
+static uint8_t t13HB [256] IBSS_ATTR;
+static uint8_t t15HB [256] IBSS_ATTR;
+static uint16_t t16HB [256] IBSS_ATTR;
+static uint16_t t24HB [256] IBSS_ATTR;
+static uint8_t t1l [ 8] IBSS_ATTR;
+static uint8_t t2l [ 9] IBSS_ATTR;
+static uint8_t t3l [ 9] IBSS_ATTR;
+static uint8_t t5l [ 16] IBSS_ATTR;
+static uint8_t t6l [ 16] IBSS_ATTR;
+static uint8_t t7l [ 36] IBSS_ATTR;
+static uint8_t t8l [ 36] IBSS_ATTR;
+static uint8_t t9l [ 36] IBSS_ATTR;
+static uint8_t t10l [ 64] IBSS_ATTR;
+static uint8_t t11l [ 64] IBSS_ATTR;
+static uint8_t t12l [ 64] IBSS_ATTR;
+static uint8_t t13l [256] IBSS_ATTR;
+static uint8_t t15l [256] IBSS_ATTR;
+static uint8_t t16l [256] IBSS_ATTR;
+static uint8_t t24l [256] IBSS_ATTR;
+static struct huffcodetab ht [HTN] IBSS_ATTR;
+
+static unsigned pcm_chunk_size IBSS_ATTR;
+static unsigned samp_per_frame IBSS_ATTR;
+
+static config_t cfg IBSS_ATTR;
static struct codec_api *ci;
-static int enc_channels;
+static char *res_buffer;
-static const uint8 ht_count_const[2][2][16] =
+static const uint8_t ht_count_const[2][2][16] =
{ { { 1, 5, 4, 5, 6, 5, 4, 4, 7, 3, 6, 0, 7, 2, 3, 1 }, /* table0 */
{ 1, 5, 5, 7, 5, 8, 7, 9, 5, 7, 7, 9, 7, 9, 9,10 } }, /* hleng0 */
{ {15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }, /* table1 */
{ 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 } } }; /* hleng1 */
-static const uint8 t1HB_const[4] = {1,1,1,0};
-static const uint8 t2HB_const[9] = {1,2,1,3,1,1,3,2,0};
-static const uint8 t3HB_const[9] = {3,2,1,1,1,1,3,2,0};
-static const uint8 t5HB_const[16] = {1,2,6,5,3,1,4,4,7,5,7,1,6,1,1,0};
-static const uint8 t6HB_const[16] = {7,3,5,1,6,2,3,2,5,4,4,1,3,3,2,0};
+static const uint8_t t1HB_const[4] = {1,1,1,0};
+static const uint8_t t2HB_const[9] = {1,2,1,3,1,1,3,2,0};
+static const uint8_t t3HB_const[9] = {3,2,1,1,1,1,3,2,0};
+static const uint8_t t5HB_const[16] = {1,2,6,5,3,1,4,4,7,5,7,1,6,1,1,0};
+static const uint8_t t6HB_const[16] = {7,3,5,1,6,2,3,2,5,4,4,1,3,3,2,0};
-static const uint8 t7HB_const[36] =
+static const uint8_t t7HB_const[36] =
{ 1, 2,10,19,16,10, 3, 3, 7,10, 5, 3,11, 4,13,17, 8, 4,
12,11,18,15,11, 2, 7, 6, 9,14, 3, 1, 6, 4, 5, 3, 2, 0 };
-static const uint8 t8HB_const[36] =
+static const uint8_t t8HB_const[36] =
{ 3, 4, 6,18,12, 5, 5, 1, 2,16, 9, 3, 7, 3, 5,14, 7, 3,
19,17,15,13,10, 4,13, 5, 8,11, 5, 1,12, 4, 4, 1, 1, 0 };
-static const uint8 t9HB_const[36] =
+static const uint8_t t9HB_const[36] =
{ 7, 5, 9,14,15, 7, 6, 4, 5, 5, 6, 7, 7, 6, 8, 8, 8, 5,
15, 6, 9,10, 5, 1,11, 7, 9, 6, 4, 1,14, 4, 6, 2, 6, 0 };
-static const uint8 t10HB_const[64] =
+static const uint8_t t10HB_const[64] =
{1,2,10,23,35,30,12,17,3,3,8,12,18,21,12,7,11,9,15,21,32,
40,19,6,14,13,22,34,46,23,18,7,20,19,33,47,27,22,9,3,31,22,
41,26,21,20,5,3,14,13,10,11,16,6,5,1,9,8,7,8,4,4,2,0 };
-static const uint8 t11HB_const[64] =
+static const uint8_t t11HB_const[64] =
{3,4,10,24,34,33,21,15,5,3,4,10,32,17,11,10,11,7,13,18,30,
31,20,5,25,11,19,59,27,18,12,5,35,33,31,58,30,16,7,5,28,26,
32,19,17,15,8,14,14,12,9,13,14,9,4,1,11,4,6,6,6,3,2,0 };
-static const uint8 t12HB_const[64] =
+static const uint8_t t12HB_const[64] =
{9,6,16,33,41,39,38,26,7,5,6,9,23,16,26,11,17,7,11,14,21,
30,10,7,17,10,15,12,18,28,14,5,32,13,22,19,18,16,9,5,40,17,
31,29,17,13,4,2,27,12,11,15,10,7,4,1,27,12,8,12,6,3,1,0 };
-static const uint8 t13HB_const[256] =
+static const uint8_t t13HB_const[256] =
{1,5,14,21,34,51,46,71,42,52,68,52,67,44,43,19,3,4,12,19,31,26,44,33,31,24,32,
24,31,35,22,14,15,13,23,36,59,49,77,65,29,40,30,40,27,33,42,16,22,20,37,61,56,
79,73,64,43,76,56,37,26,31,25,14,35,16,60,57,97,75,114,91,54,73,55,41,48,53,
@@ -234,7 +235,7 @@ static const uint8 t13HB_const[256] =
45,21,34,64,56,50,49,45,31,19,12,15,10,7,6,3,48,23,20,39,36,35,53,21,16,23,13,
10,6,1,4,2,16,15,17,27,25,20,29,11,17,12,16,8,1,1,0,1 };
-static const uint8 t15HB_const[256] =
+static const uint8_t t15HB_const[256] =
{7,12,18,53,47,76,124,108,89,123,108,119,107,81,122,63,13,5,16,27,46,36,61,51,
42,70,52,83,65,41,59,36,19,17,15,24,41,34,59,48,40,64,50,78,62,80,56,33,29,28,
25,43,39,63,55,93,76,59,93,72,54,75,50,29,52,22,42,40,67,57,95,79,72,57,89,69,
@@ -246,7 +247,7 @@ static const uint8 t15HB_const[256] =
24,16,22,13,14,7,91,44,39,38,34,63,52,45,31,52,28,19,14,8,9,3,123,60,58,53,47,
43,32,22,37,24,17,12,15,10,2,1,71,37,34,30,28,20,17,26,21,16,10,6,8,6,2,0};
-static const uint16 t16HB_const[256] =
+static const uint16_t t16HB_const[256] =
{1,5,14,44,74,63,110,93,172,149,138,242,225,195,376,17,3,4,12,20,35,62,53,47,
83,75,68,119,201,107,207,9,15,13,23,38,67,58,103,90,161,72,127,117,110,209,
206,16,45,21,39,69,64,114,99,87,158,140,252,212,199,387,365,26,75,36,68,65,
@@ -261,7 +262,7 @@ static const uint16 t16HB_const[256] =
358,711,709,866,1734,871,3458,870,434,0,12,10,7,11,10,17,11,9,13,12,10,7,5,3,
1,3};
-static const uint16 t24HB_const[256] =
+static const uint16_t t24HB_const[256] =
{15,13,46,80,146,262,248,434,426,669,653,649,621,517,1032,88,14,12,21,38,71,
130,122,216,209,198,327,345,319,297,279,42,47,22,41,74,68,128,120,221,207,194,
182,340,315,295,541,18,81,39,75,70,134,125,116,220,204,190,178,325,311,293,
@@ -276,7 +277,7 @@ static const uint16 t24HB_const[256] =
374,369,365,361,357,2,1033,280,278,274,267,264,259,382,378,372,367,363,360,
358,356,0,43,20,19,17,15,13,11,9,7,6,4,7,5,3,1,3};
-static const uint32 tab1315_const[256] =
+static const uint32_t tab1315_const[256] =
{ 0x010003,0x050005,0x070006,0x080008,0x090008,0x0a0009,0x0a000a,0x0b000a,
0x0a000a,0x0b000b,0x0c000b,0x0c000c,0x0d000c,0x0d000c,0x0e000d,0x0e000e,
0x040005,0x060005,0x080007,0x090008,0x0a0009,0x0a0009,0x0b000a,0x0b000a,
@@ -310,18 +311,18 @@ static const uint32 tab1315_const[256] =
0x0d000d,0x0e000d,0x0f000d,0x10000d,0x10000d,0x10000d,0x11000d,0x10000e,
0x11000e,0x11000e,0x12000e,0x12000e,0x15000f,0x14000f,0x15000f,0x12000f };
-static const uint32 tab01_const[16] =
+static const uint32_t tab01_const[16] =
{ 0x10004,0x50005,0x50005,0x70006,0x50005,0x80006,0x70006,0x90007,
0x50005,0x70006,0x70006,0x90007,0x70006,0x90007,0x90007,0xa0008 };
-static const uint32 tab23_const[ 9] =
+static const uint32_t tab23_const[ 9] =
{ 0x10002,0x40003,0x70007,0x40004,0x50004,0x70007,0x60006,0x70007,0x80008 };
-static const uint32 tab56_const[16] =
+static const uint32_t tab56_const[16] =
{ 0x10003,0x40004,0x70006,0x80008,0x40004,0x50004,0x80006,0x90007,
0x70005,0x80006,0x90007,0xa0008,0x80007,0x80007,0x90008,0xa0009 };
-static const uint32 tab789_const[36] =
+static const uint32_t tab789_const[36] =
{0x00100803,0x00401004,0x00701c06,0x00902407,0x00902409,0x00a0280a,0x00401004,
0x00601005,0x00801806,0x00902807,0x00902808,0x00a0280a,0x00701c05,0x00701806,
0x00902007,0x00a02808,0x00a02809,0x00b02c0a,0x00802407,0x00902807,0x00a02808,
@@ -329,7 +330,7 @@ static const uint32 tab789_const[36] =
0x00b0300a,0x00c0300b,0x00902809,0x00a02809,0x00b02c0a,0x00c02c0a,0x00c0340b,
0x00c0340b};
-static const uint32 tabABC_const[64] =
+static const uint32_t tabABC_const[64] =
{0x00100804,0x00401004,0x00701806,0x00902008,0x00a02409,0x00a0280a,0x00a0240a,
0x00b0280a,0x00401004,0x00601405,0x00801806,0x00902007,0x00a02809,0x00b02809,
0x00a0240a,0x00a0280a,0x00701806,0x00801c06,0x00902007,0x00a02408,0x00b02809,
@@ -341,7 +342,7 @@ static const uint32 tabABC_const[64] =
0x00a0240a,0x00a0240a,0x00b0280a,0x00c02c0b,0x00c0300b,0x00d0300b,0x00d0300b,
0x00d0300c};
-static const uint32 tab1624_const[256] =
+static const uint32_t tab1624_const[256] =
{0x00010004,0x00050005,0x00070007,0x00090008,0x000a0009,0x000a000a,0x000b000a,
0x000b000b,0x000c000b,0x000c000c,0x000c000c,0x000d000c,0x000d000c,0x000d000c,
0x000e000d,0x000a000a,0x00040005,0x00060006,0x00080007,0x00090008,0x000a0009,
@@ -380,34 +381,34 @@ static const uint32 tab1624_const[256] =
0x000c0009,0x000c0009,0x000c0009,0x000d0009,0x000d0009,0x000d0009,0x000d000a,
0x000d000a,0x000d000a,0x000d000a,0x000a0006};
-static const uint8 t1l_const[8] = {1,3,2,3,1,4,3,5};
-static const uint8 t2l_const[9] = {1,3,6,3,3,5,5,5,6};
-static const uint8 t3l_const[9] = {2,2,6,3,2,5,5,5,6};
-static const uint8 t5l_const[16] = {1,3,6,7,3,3,6,7,6,6,7,8,7,6,7,8};
-static const uint8 t6l_const[16] = {3,3,5,7,3,2,4,5,4,4,5,6,6,5,6,7};
+static const uint8_t t1l_const[8] = {1,3,2,3,1,4,3,5};
+static const uint8_t t2l_const[9] = {1,3,6,3,3,5,5,5,6};
+static const uint8_t t3l_const[9] = {2,2,6,3,2,5,5,5,6};
+static const uint8_t t5l_const[16] = {1,3,6,7,3,3,6,7,6,6,7,8,7,6,7,8};
+static const uint8_t t6l_const[16] = {3,3,5,7,3,2,4,5,4,4,5,6,6,5,6,7};
-static const uint8 t7l_const[36] =
+static const uint8_t t7l_const[36] =
{1,3,6,8,8,9,3,4,6,7,7,8,6,5,7,8,8,9,7,7,8,9,9,9,7,7,8,9,9,10,8,8,9,10,10,10};
-static const uint8 t8l_const[36] =
+static const uint8_t t8l_const[36] =
{2,3,6,8,8,9,3,2,4,8,8,8,6,4,6,8,8,9,8,8,8,9,9,10,8,7,8,9,10,10,9,8,9,9,11,11};
-static const uint8 t9l_const[36] =
+static const uint8_t t9l_const[36] =
{3,3,5,6,8,9,3,3,4,5,6,8,4,4,5,6,7,8,6,5,6,7,7,8,7,6,7,7,8,9,8,7,8,8,9,9};
-static const uint8 t10l_const[64] =
+static const uint8_t t10l_const[64] =
{1,3,6,8,9,9,9,10,3,4,6,7,8,9,8,8,6,6,7,8,9,10,9,9,7,7,8,9,10,10,9,10,8,8,9,10,
10,10,10,10,9,9,10,10,11,11,10,11,8,8,9,10,10,10,11,11,9,8,9,10,10,11,11,11};
-static const uint8 t11l_const[64] =
+static const uint8_t t11l_const[64] =
{2,3,5,7,8,9,8,9,3,3,4,6,8,8,7,8,5,5,6,7,8,9,8,8,7,6,7,9,8,10,8,9,8,8,8,9,9,10,
9,10,8,8,9,10,10,11,10,11,8,7,7,8,9,10,10,10,8,7,8,9,10,10,10,10};
-static const uint8 t12l_const[64] =
+static const uint8_t t12l_const[64] =
{4,3,5,7,8,9,9,9,3,3,4,5,7,7,8,8,5,4,5,6,7,8,7,8,6,5,6,6,7,8,8,8,7,6,7,7,8,
8,8,9,8,7,8,8,8,9,8,9,8,7,7,8,8,9,9,10,9,8,8,9,9,9,9,10};
-static const uint8 t13l_const[256] =
+static const uint8_t t13l_const[256] =
{1,4,6,7,8,9,9,10,9,10,11,11,12,12,13,13,3,4,6,7,8,8,9,9,9,9,10,10,11,12,12,12,
6,6,7,8,9,9,10,10,9,10,10,11,11,12,13,13,7,7,8,9,9,10,10,10,10,11,11,11,11,12,
13,13,8,7,9,9,10,10,11,11,10,11,11,12,12,13,13,14,9,8,9,10,10,10,11,11,11,11,
@@ -419,7 +420,7 @@ static const uint8 t13l_const[256] =
16,16,13,12,12,13,13,13,15,14,14,17,15,15,15,17,16,16,12,12,13,14,14,14,15,14,
15,15,16,16,19,18,19,16};
-static const uint8 t15l_const[256] =
+static const uint8_t t15l_const[256] =
{3,4,5,7,7,8,9,9,9,10,10,11,11,11,12,13,4,3,5,6,7,7,8,8,8,9,9,10,10,10,11,11,5,
5,5,6,7,7,8,8,8,9,9,10,10,11,11,11,6,6,6,7,7,8,8,9,9,9,10,10,10,11,11,11,7,6,
7,7,8,8,9,9,9,9,10,10,10,11,11,11,8,7,7,8,8,8,9,9,9,9,10,10,11,11,11,12,9,7,8,
@@ -430,7 +431,7 @@ static const uint8 t15l_const[256] =
11,11,11,11,12,12,12,12,12,13,13,12,11,11,11,11,11,11,11,12,12,12,12,13,13,12,
13,12,11,11,11,11,11,11,12,12,12,12,12,13,13,13,13};
-static const uint8 t16l_const[256] =
+static const uint8_t t16l_const[256] =
{1,4,6,8,9,9,10,10,11,11,11,12,12,12,13,9,3,4,6,7,8,9,9,9,10,10,10,11,12,11,12,
8,6,6,7,8,9,9,10,10,11,10,11,11,11,12,12,9,8,7,8,9,9,10,10,10,11,11,12,12,12,
13,13,10,9,8,9,9,10,10,11,11,11,12,12,12,13,13,13,9,9,8,9,9,10,11,11,12,11,12,
@@ -442,7 +443,7 @@ static const uint8 t16l_const[256] =
17,15,11,13,13,11,12,14,14,13,14,14,15,16,15,17,15,14,11,9,8,8,9,9,10,10,10,
11,11,11,11,11,11,11,8};
-static const uint8 t24l_const[256] =
+static const uint8_t t24l_const[256] =
{4,4,6,7,8,9,9,10,10,11,11,11,11,11,12,9,4,4,5,6,7,8,8,9,9,9,10,10,10,10,10,8,
6,5,6,7,7,8,8,9,9,9,9,10,10,10,11,7,7,6,7,7,8,8,8,9,9,9,9,10,10,10,10,7,8,7,7,
8,8,8,8,9,9,9,10,10,10,10,11,7,9,7,8,8,8,8,9,9,9,9,10,10,10,10,10,7,9,8,8,8,8,
@@ -491,8 +492,8 @@ static const struct huffcodebig ht_big[HTN] =
static const struct
{
- uint32 region0_cnt;
- uint32 region1_cnt;
+ uint32_t region0_cnt;
+ uint32_t region1_cnt;
} subdv_table[23] =
{ {0, 0}, /* 0 bands */
{0, 0}, /* 1 bands */
@@ -519,7 +520,7 @@ static const struct
{6, 7}, /* 22 bands */
};
-static const uint32 sfBand[6][23] =
+static const uint32_t sfBand[6][23] =
{
/* Table B.2.b: 22.05 kHz */
{0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576},
@@ -747,9 +748,13 @@ static const int order[32] =
{ 0, 1, 16, 17, 8, 9, 24, 25, 4, 5, 20, 21, 12, 13, 28, 29,
2, 3, 18, 19,10,11, 26, 27, 6, 7, 22, 23, 14, 15, 30, 31 };
-static const int bitr_index[2][15] =
-{ {0, 8,16,24,32,40,48,56, 64, 80, 96,112,128,144,160},
- {0,32,40,48,56,64,80,96,112,128,160,192,224,256,320} };
+static const long sampr_index[2][3] =
+{ { 22050, 24000, 16000 }, /* MPEG 2 */
+ { 44100, 48000, 32000 } }; /* MPEG 1 */
+
+static const long bitr_index[2][15] =
+{ {0, 8,16,24,32,40,48,56, 64, 80, 96,112,128,144,160}, /* MPEG 2 */
+ {0,32,40,48,56,64,80,96,112,128,160,192,224,256,320} }; /* MPEG 1 */
static const int num_bands[3][15] =
{ {0,10,10,10,10,12,14,16, 20, 22, 24, 26, 28, 30, 32},
@@ -837,35 +842,55 @@ static const int win_const[18][4] = {
{ 134, -146,-3352,-3072 } };
/* forward declarations */
-int HuffmanCode( short *ix, int *xr, uint32 begin, uint32 end, int table);
-int HuffmanCod1( short *ix, int *xr, uint32 begin, uint32 end, int table);
-void putbits(uint32 val, uint32 nbit);
-int find_best_2( short *ix, uint32 start, uint32 end, const uint32 *table,
- uint32 len, int *bits);
-int find_best_3( short *ix, uint32 start, uint32 end, const uint32 *table,
- uint32 len, int *bits);
-int count_bit1 ( short *ix, uint32 start, uint32 end, int *bits );
-int count_bigv ( short *ix, uint32 start, uint32 end, int table0, int table1,
+static int HuffmanCode( short *ix, int *xr, uint32_t begin, uint32_t end, int table);
+static int HuffmanCod1( short *ix, int *xr, uint32_t begin, uint32_t end, int table);
+static void putbits(uint32_t val, uint32_t nbit);
+static int find_best_2( short *ix, uint32_t start, uint32_t end, const uint32_t *table,
+ uint32_t len, int *bits);
+static int find_best_3( short *ix, uint32_t start, uint32_t end, const uint32_t *table,
+ uint32_t len, int *bits);
+static int count_bit1 ( short *ix, uint32_t start, uint32_t end, int *bits );
+static int count_bigv ( short *ix, uint32_t start, uint32_t end, int table0, int table1,
int *bits);
-void encodeSideInfo( side_info_t si[2][2] )
+static void encodeSideInfo( side_info_t si[2][2] )
{
int gr, ch, header;
- uint32 cc=0, sz=0;
+ uint32_t cc=0, sz=0;
- header = 0xfff00000;
- header |= cfg.mpg.type << 19; /* mp3 type: 1 */
- header |= 1 << 17; /* mp3 layer: 1 */
- header |= 1 << 16; /* mp3 crc: 0 */
+ /*
+ * MPEG header layout:
+ * AAAAAAAA AAABBCCD EEEEFFGH IIJJKLMM
+ * A (31-21) = frame sync
+ * B (20-19) = MPEG type
+ * C (18-17) = MPEG layer
+ * D (16) = protection bit
+ * E (15-12) = bitrate index
+ * F (11-10) = samplerate index
+ * G (9) = padding bit
+ * H (8) = private bit
+ * I (7-6) = channel mode
+ * J (5-4) = mode extension (jstereo only)
+ * K (3) = copyright bit
+ * L (2) = original
+ * M (1-0) = emphasis
+ */
+
+ header = (0xfff00000) | /* frame sync (AAAAAAAAA AAA)
+ mp3 type (upper): 1 (B) */
+ (0x01 << 17) | /* mp3 layer: 01 (CC) */
+ ( 0x1 << 16) | /* mp3 crc: 1 (D) */
+ ( 0x1 << 2); /* mp3 org: 1 (L) */
+ header |= cfg.mpg.type << 19;
header |= cfg.mpg.bitr_id << 12;
header |= cfg.mpg.smpl_id << 10;
header |= cfg.mpg.padding << 9;
header |= cfg.mpg.mode << 6;
- header |= 1 << 2; /* mp3 original: 1 */
+ /* no emphasis (bits 0-1) */
putbits( header, 32 );
- if(cfg.mpg.type)
+ if(cfg.mpg.type == 1)
{ /* MPEG1 */
if(cfg.channels == 2) { putlong( 0, 20); }
else { putlong( 0, 18); }
@@ -910,7 +935,7 @@ void encodeSideInfo( side_info_t si[2][2] )
/* Note the discussion of huffmancodebits() on pages 28 and 29 of the IS,
as well as the definitions of the side information on pages 26 and 27. */
-void Huffmancodebits( short *ix, int *xr, side_info_t *gi )
+static void Huffmancodebits( short *ix, int *xr, side_info_t *gi )
{
int region1 = gi->address1;
int region2 = gi->address2;
@@ -944,10 +969,10 @@ void Huffmancodebits( short *ix, int *xr, side_info_t *gi )
}
}
-int HuffmanCod1( short *ix, int *xr, uint32 begin, uint32 end, int tbl)
+int HuffmanCod1( short *ix, int *xr, uint32_t begin, uint32_t end, int tbl)
{
- uint32 cc=0, sz=0;
- uint32 i, d, p;
+ uint32_t cc=0, sz=0;
+ uint32_t i, d, p;
int sumbit=0, s=0, l=0, v, w, x, y;
#define sgnv (xr[i+0] < 0 ? 1 : 0)
#define sgnw (xr[i+1] < 0 ? 1 : 0)
@@ -995,10 +1020,10 @@ int HuffmanCod1( short *ix, int *xr, uint32 begin, uint32 end, int tbl)
}
/* Implements the pseudocode of page 98 of the IS */
-int HuffmanCode( short *ix, int *xr, uint32 begin, uint32 end, int table)
+int HuffmanCode( short *ix, int *xr, uint32_t begin, uint32_t end, int table)
{
- uint32 cc=0, sz=0, code;
- uint32 i, xl=0, yl=0, idx;
+ uint32_t cc=0, sz=0, code;
+ uint32_t i, xl=0, yl=0, idx;
int x, y, bit, sumbit=0;
#define sign_x (xr[i+0] < 0 ? 1 : 0)
#define sign_y (xr[i+1] < 0 ? 1 : 0)
@@ -1008,9 +1033,9 @@ int HuffmanCode( short *ix, int *xr, uint32 begin, uint32 end, int table)
if( table > 15 )
{ /* ESC-table is used */
- uint32 linbits = ht_big[table-16].linbits;
- uint16 *hffcode = table < 24 ? t16HB : t24HB;
- uint8 *hlen = table < 24 ? t16l : t24l;
+ uint32_t linbits = ht_big[table-16].linbits;
+ uint16_t *hffcode = table < 24 ? t16HB : t24HB;
+ uint8_t *hlen = table < 24 ? t16l : t24l;
for(i=begin; i<end; i+=2)
{
@@ -1088,14 +1113,14 @@ int HuffmanCode( short *ix, int *xr, uint32 begin, uint32 end, int table)
return sumbit;
}
-void putbits(uint32 val, uint32 nbit)
+void putbits(uint32_t val, uint32_t nbit)
{
int new_bitpos = CodedData.bitpos + nbit;
int ptrpos = CodedData.bitpos >> 5;
val = val & (0xffffffff >> (32 - nbit));
- /* data fit in one uint32 */
+ /* data fit in one uint32_t */
if(((new_bitpos - 1) >> 5) == ptrpos)
CodedData.bbuf[ptrpos] |= val << ((32 - new_bitpos) & 31);
else
@@ -1114,9 +1139,9 @@ void putbits(uint32 val, uint32 nbit)
/* of the Huffman tables as defined in the IS (Table B.7), and will not */
/* work with any arbitrary tables. */
/***************************************************************************/
-int choose_table( short *ix, uint32 begin, uint32 end, int *bits )
+int choose_table( short *ix, uint32_t begin, uint32_t end, int *bits )
{
- uint32 i;
+ uint32_t i;
int max, table0, table1;
for(i=begin,max=0; i<end; i++)
@@ -1158,10 +1183,10 @@ int choose_table( short *ix, uint32 begin, uint32 end, int *bits )
}
}
-int find_best_2(short *ix, uint32 start, uint32 end, const uint32 *table,
- uint32 len, int *bits)
+int find_best_2(short *ix, uint32_t start, uint32_t end, const uint32_t *table,
+ uint32_t len, int *bits)
{
- uint32 i, sum = 0;
+ uint32_t i, sum = 0;
for(i=start; i<end; i+=2)
sum += table[ix[i] * len + ix[i+1]];
@@ -1178,10 +1203,10 @@ int find_best_2(short *ix, uint32 start, uint32 end, const uint32 *table,
}
}
-int find_best_3(short *ix, uint32 start, uint32 end, const uint32 *table,
- uint32 len, int *bits)
+int find_best_3(short *ix, uint32_t start, uint32_t end, const uint32_t *table,
+ uint32_t len, int *bits)
{
- uint32 i, j, sum = 0;
+ uint32_t i, j, sum = 0;
int sum1 = 0;
int sum2 = 0;
int sum3 = 0;
@@ -1211,9 +1236,9 @@ int find_best_3(short *ix, uint32 start, uint32 end, const uint32 *table,
/*************************************************************************/
/* Function: Count the number of bits necessary to code the subregion. */
/*************************************************************************/
-int count_bit1(short *ix, uint32 start, uint32 end, int *bits )
+int count_bit1(short *ix, uint32_t start, uint32_t end, int *bits )
{
- uint32 i, sum = 0;
+ uint32_t i, sum = 0;
for(i=start; i<end; i+=2)
sum += t1l[4 + ix[i] * 2 + ix[i+1]];
@@ -1223,10 +1248,10 @@ int count_bit1(short *ix, uint32 start, uint32 end, int *bits )
return 1; /* this is table1 */
}
-int count_bigv(short *ix, uint32 start, uint32 end, int table0,
+int count_bigv(short *ix, uint32_t start, uint32_t end, int table0,
int table1, int *bits )
{
- uint32 i, sum0, sum1, sum=0, bigv=0, x, y;
+ uint32_t i, sum0, sum1, sum=0, bigv=0, x, y;
/* ESC-table is used */
for(i=start; i<end; i+=2)
@@ -1264,7 +1289,7 @@ int calc_runlen( short *ix, side_info_t *si )
int p, i, sum = 0;
for(i=SAMPL2; i-=2; )
- if(*(uint32*)&ix[i-2]) /* !!!! short *ix; !!!!! */
+ if(*(uint32_t*)&ix[i-2]) /* !!!! short *ix; !!!!! */
break;
si->count1 = 0;
@@ -1899,276 +1924,275 @@ void mdct_long(int *out, int *in)
out[16] = ct - st;
}
-static int find_bitrate_index(int type, int bitrate)
+static int find_bitrate_index(int type, int bitrate, bool stereo)
{
- int i;
+ if (type == 1 && !stereo && bitrate > 160)
+ bitrate = 160;
- for(i=0;i<14;i++)
- if(bitrate == bitr_index[type][i])
- break;
-
- return i;
+ return ci->round_value_to_list32(bitrate,
+ &bitr_index[type][1], 14, true) + 1;
}
static int find_samplerate_index(long freq, int *mp3_type)
-{ /* MPEG 2 */ /* MPEG 1 */
- static long mpeg[2][3] = { {22050, 24000, 16000}, {44100, 48000, 32000} };
- int mpg, rate;
-
- /* set default values: MPEG1 at 44100/s */
- *mp3_type = 1;
-
- for(mpg=0; mpg<2; mpg++)
- for(rate=0; rate<3; rate++)
- if(freq == mpeg[mpg][rate])
- { *mp3_type = mpg; return rate; }
-
- return 0;
+{
+ int mpeg = freq >= (32000+24000)/2 ? 1 : 0;
+ int i = ci->round_value_to_list32(freq, sampr_index[mpeg], 3, true);
+ *mp3_type = mpeg;
+ return i;
}
-void init_mp3_encoder_engine(bool stereo, int quality, int sample_rate)
+bool init_mp3_encoder_engine(int sample_rate,
+ int num_channels,
+ struct encoder_config *enc_cfg)
{
- /* keep in sync with rec_quality_info_afmt in id3.h/.c */
- static int bitr_s[9] = { 64, 96, 128, 160, 192, 224, 320, 64, 64 };
- static int bitr_m[9] = { 64, 96, 128, 160, 160, 160, 160, 64, 64 };
- uint32 avg_byte_per_frame;
-
- if(quality == 0 && stereo && sample_rate >= 32000)
- { /* use MPEG2 format */
- sample_rate >>= 1;
- cfg.resample = 1;
- cfg.granules = 1;
- }
- else
- { /* use MPEG1 format */
- cfg.resample = 0;
- cfg.granules = 2;
- }
+ const bool stereo = num_channels > 1;
+ uint32_t avg_byte_per_frame;
+
+ cfg.channels = stereo ? 2 : 1;
+ cfg.mpg.mode = stereo ? 0 : 3; /* 0=stereo, 3=mono */
+ cfg.mpg.smpl_id = find_samplerate_index(sample_rate, &cfg.mpg.type);
+ cfg.samplerate = sampr_index[cfg.mpg.type][cfg.mpg.smpl_id];
+ cfg.mpg.bitr_id = find_bitrate_index(cfg.mpg.type,
+ enc_cfg->mp3_enc.bitrate,
+ stereo);
+ cfg.mpg.bitrate = bitr_index[cfg.mpg.type][cfg.mpg.bitr_id];
+ cfg.mpg.num_bands = num_bands[stereo ? cfg.mpg.type : 2][cfg.mpg.bitr_id];
+
+ if (cfg.mpg.type == 1)
+ {
+ cfg.granules = 2;
+ pcm_chunk_size = PCM_CHUNK_SIZE1;
+ samp_per_frame = SAMP_PER_FRAME1;
+ }
+ else
+ {
+ cfg.granules = 1;
+ pcm_chunk_size = PCM_CHUNK_SIZE2;
+ samp_per_frame = SAMP_PER_FRAME2;
+ }
- cfg.byte_order = order_bigEndian;
- cfg.samplerate = sample_rate;
- cfg.channels = stereo ? 2 : 1;
- cfg.mpg.mode = stereo ? 0 : 3; /* 0=stereo, 3=mono */
- cfg.mpg.bitrate = stereo ? bitr_s[quality] : bitr_m[quality];
- cfg.mpg.smpl_id = find_samplerate_index(cfg.samplerate, &cfg.mpg.type);
- cfg.mpg.bitr_id = find_bitrate_index(cfg.mpg.type, cfg.mpg.bitrate);
- cfg.mpg.num_bands = num_bands[stereo ? cfg.mpg.type : 2][cfg.mpg.bitr_id];
-
- memcpy(scalefac, sfBand[cfg.mpg.smpl_id + 3*cfg.mpg.type], sizeof(scalefac));
- memset(mfbuf , 0 , sizeof(mfbuf ));
- memset(mdct_freq , 0 , sizeof(mdct_freq ));
- memset(enc_data , 0 , sizeof(enc_data ));
- memset(sb_data , 0 , sizeof(sb_data ));
- memset(&CodedData, 0 , sizeof(CodedData ));
- memcpy(ca , ca_const , sizeof(ca ));
- memcpy(cs , cs_const , sizeof(cs ));
- memcpy(cx , cx_const , sizeof(cx ));
- memcpy(win , win_const , sizeof(win ));
- memcpy(enwindow , enwindow_const , sizeof(enwindow ));
- memcpy(int2idx , int2idx_const , sizeof(int2idx ));
- memcpy(ht_count , ht_count_const , sizeof(ht_count ));
- memcpy( tab01 , tab01_const , sizeof(tab01 ));
- memcpy( tab23 , tab23_const , sizeof(tab23 ));
- memcpy( tab56 , tab56_const , sizeof(tab56 ));
- memcpy( tab1315 , tab1315_const , sizeof(tab1315 ));
- memcpy( tab1624 , tab1624_const , sizeof(tab1624 ));
- memcpy( tab789 , tab789_const , sizeof(tab789 ));
- memcpy( tabABC , tabABC_const , sizeof(tabABC ));
- memcpy( t1HB , t1HB_const , sizeof(t1HB ));
- memcpy( t2HB , t2HB_const , sizeof(t2HB ));
- memcpy( t3HB , t3HB_const , sizeof(t3HB ));
- memcpy( t5HB , t5HB_const , sizeof(t5HB ));
- memcpy( t6HB , t6HB_const , sizeof(t6HB ));
- memcpy( t7HB , t7HB_const , sizeof(t7HB ));
- memcpy( t8HB , t8HB_const , sizeof(t8HB ));
- memcpy( t9HB , t9HB_const , sizeof(t9HB ));
- memcpy(t10HB , t10HB_const , sizeof(t10HB ));
- memcpy(t11HB , t11HB_const , sizeof(t11HB ));
- memcpy(t12HB , t12HB_const , sizeof(t12HB ));
- memcpy(t13HB , t13HB_const , sizeof(t13HB ));
- memcpy(t15HB , t15HB_const , sizeof(t15HB ));
- memcpy(t16HB , t16HB_const , sizeof(t16HB ));
- memcpy(t24HB , t24HB_const , sizeof(t24HB ));
- memcpy( t1l , t1l_const , sizeof(t1l ));
- memcpy( t2l , t2l_const , sizeof(t2l ));
- memcpy( t3l , t3l_const , sizeof(t3l ));
- memcpy( t5l , t5l_const , sizeof(t5l ));
- memcpy( t6l , t6l_const , sizeof(t6l ));
- memcpy( t7l , t7l_const , sizeof(t7l ));
- memcpy( t8l , t8l_const , sizeof(t8l ));
- memcpy( t9l , t9l_const , sizeof(t9l ));
- memcpy(t10l , t10l_const , sizeof(t10l ));
- memcpy(t11l , t11l_const , sizeof(t11l ));
- memcpy(t12l , t12l_const , sizeof(t12l ));
- memcpy(t13l , t13l_const , sizeof(t13l ));
- memcpy(t15l , t15l_const , sizeof(t15l ));
- memcpy(t16l , t16l_const , sizeof(t16l ));
- memcpy(t24l , t24l_const , sizeof(t24l ));
- memcpy(ht , ht_const , sizeof(ht ));
-
- ht[ 0].table = NULL; ht[ 0].hlen = NULL; /* Apparently not used */
- ht[ 1].table = t1HB; ht[ 1].hlen = t1l;
- ht[ 2].table = t2HB; ht[ 2].hlen = t2l;
- ht[ 3].table = t3HB; ht[ 3].hlen = t3l;
- ht[ 4].table = NULL; ht[ 4].hlen = NULL; /* Apparently not used */
- ht[ 5].table = t5HB; ht[ 5].hlen = t5l;
- ht[ 6].table = t6HB; ht[ 6].hlen = t6l;
- ht[ 7].table = t7HB; ht[ 7].hlen = t7l;
- ht[ 8].table = t8HB; ht[ 8].hlen = t8l;
- ht[ 9].table = t9HB; ht[ 9].hlen = t9l;
- ht[10].table = t10HB; ht[10].hlen = t10l;
- ht[11].table = t11HB; ht[11].hlen = t11l;
- ht[12].table = t12HB; ht[12].hlen = t12l;
- ht[13].table = t13HB; ht[13].hlen = t13l;
- ht[14].table = NULL; ht[14].hlen = NULL; /* Apparently not used */
- ht[15].table = t15HB; ht[15].hlen = t15l;
-
- /* Figure average number of 'bytes' per frame */
- avg_byte_per_frame = SAMPL2 * 16000 * cfg.mpg.bitrate / (2 - cfg.mpg.type);
- avg_byte_per_frame = avg_byte_per_frame / cfg.samplerate;
- cfg.byte_per_frame = avg_byte_per_frame / 64;
- cfg.frac_per_frame = avg_byte_per_frame & 63;
- cfg.slot_lag = 0;
- cfg.sideinfo_len = 32 + (cfg.mpg.type ? (cfg.channels == 1 ? 136 : 256)
- : (cfg.channels == 1 ? 72 : 136));
+ memcpy(scalefac, sfBand[cfg.mpg.smpl_id + 3*cfg.mpg.type], sizeof(scalefac));
+ memset(mfbuf , 0 , sizeof(mfbuf ));
+ memset(mdct_freq , 0 , sizeof(mdct_freq ));
+ memset(enc_data , 0 , sizeof(enc_data ));
+ memset(sb_data , 0 , sizeof(sb_data ));
+ memset(&CodedData, 0 , sizeof(CodedData ));
+ memcpy(ca , ca_const , sizeof(ca ));
+ memcpy(cs , cs_const , sizeof(cs ));
+ memcpy(cx , cx_const , sizeof(cx ));
+ memcpy(win , win_const , sizeof(win ));
+ memcpy(enwindow , enwindow_const , sizeof(enwindow ));
+ memcpy(int2idx , int2idx_const , sizeof(int2idx ));
+ memcpy(ht_count , ht_count_const , sizeof(ht_count ));
+ memcpy( tab01 , tab01_const , sizeof(tab01 ));
+ memcpy( tab23 , tab23_const , sizeof(tab23 ));
+ memcpy( tab56 , tab56_const , sizeof(tab56 ));
+ memcpy( tab1315 , tab1315_const , sizeof(tab1315 ));
+ memcpy( tab1624 , tab1624_const , sizeof(tab1624 ));
+ memcpy( tab789 , tab789_const , sizeof(tab789 ));
+ memcpy( tabABC , tabABC_const , sizeof(tabABC ));
+ memcpy( t1HB , t1HB_const , sizeof(t1HB ));
+ memcpy( t2HB , t2HB_const , sizeof(t2HB ));
+ memcpy( t3HB , t3HB_const , sizeof(t3HB ));
+ memcpy( t5HB , t5HB_const , sizeof(t5HB ));
+ memcpy( t6HB , t6HB_const , sizeof(t6HB ));
+ memcpy( t7HB , t7HB_const , sizeof(t7HB ));
+ memcpy( t8HB , t8HB_const , sizeof(t8HB ));
+ memcpy( t9HB , t9HB_const , sizeof(t9HB ));
+ memcpy(t10HB , t10HB_const , sizeof(t10HB ));
+ memcpy(t11HB , t11HB_const , sizeof(t11HB ));
+ memcpy(t12HB , t12HB_const , sizeof(t12HB ));
+ memcpy(t13HB , t13HB_const , sizeof(t13HB ));
+ memcpy(t15HB , t15HB_const , sizeof(t15HB ));
+ memcpy(t16HB , t16HB_const , sizeof(t16HB ));
+ memcpy(t24HB , t24HB_const , sizeof(t24HB ));
+ memcpy( t1l , t1l_const , sizeof(t1l ));
+ memcpy( t2l , t2l_const , sizeof(t2l ));
+ memcpy( t3l , t3l_const , sizeof(t3l ));
+ memcpy( t5l , t5l_const , sizeof(t5l ));
+ memcpy( t6l , t6l_const , sizeof(t6l ));
+ memcpy( t7l , t7l_const , sizeof(t7l ));
+ memcpy( t8l , t8l_const , sizeof(t8l ));
+ memcpy( t9l , t9l_const , sizeof(t9l ));
+ memcpy(t10l , t10l_const , sizeof(t10l ));
+ memcpy(t11l , t11l_const , sizeof(t11l ));
+ memcpy(t12l , t12l_const , sizeof(t12l ));
+ memcpy(t13l , t13l_const , sizeof(t13l ));
+ memcpy(t15l , t15l_const , sizeof(t15l ));
+ memcpy(t16l , t16l_const , sizeof(t16l ));
+ memcpy(t24l , t24l_const , sizeof(t24l ));
+ memcpy(ht , ht_const , sizeof(ht ));
+
+ ht[ 0].table = NULL; ht[ 0].hlen = NULL; /* Apparently not used */
+ ht[ 1].table = t1HB; ht[ 1].hlen = t1l;
+ ht[ 2].table = t2HB; ht[ 2].hlen = t2l;
+ ht[ 3].table = t3HB; ht[ 3].hlen = t3l;
+ ht[ 4].table = NULL; ht[ 4].hlen = NULL; /* Apparently not used */
+ ht[ 5].table = t5HB; ht[ 5].hlen = t5l;
+ ht[ 6].table = t6HB; ht[ 6].hlen = t6l;
+ ht[ 7].table = t7HB; ht[ 7].hlen = t7l;
+ ht[ 8].table = t8HB; ht[ 8].hlen = t8l;
+ ht[ 9].table = t9HB; ht[ 9].hlen = t9l;
+ ht[10].table = t10HB; ht[10].hlen = t10l;
+ ht[11].table = t11HB; ht[11].hlen = t11l;
+ ht[12].table = t12HB; ht[12].hlen = t12l;
+ ht[13].table = t13HB; ht[13].hlen = t13l;
+ ht[14].table = NULL; ht[14].hlen = NULL; /* Apparently not used */
+ ht[15].table = t15HB; ht[15].hlen = t15l;
+
+ /* Figure average number of 'bytes' per frame */
+ avg_byte_per_frame = SAMPL2 * 16000 * cfg.mpg.bitrate / (2 - cfg.mpg.type);
+ avg_byte_per_frame = avg_byte_per_frame / cfg.samplerate;
+ cfg.byte_per_frame = avg_byte_per_frame / 64;
+ cfg.frac_per_frame = avg_byte_per_frame & 63;
+ cfg.slot_lag = 0;
+ cfg.sideinfo_len = 32 + (cfg.mpg.type ? (cfg.channels == 1 ? 136 : 256)
+ : (cfg.channels == 1 ? 72 : 136));
+
+ return true;
}
-
-enum codec_status codec_start(struct codec_api* api)
+static void to_mono_mm(void) ICODE_ATTR;
+static void to_mono_mm(void)
{
- int i, ii, gr, k, ch, shift, gr_cnt;
- int max, min;
- long *buffer;
- int chunk_size, num_chunks;
- int enc_buffer_size;
- int enc_quality;
- uint32 *mp3_chunk_ptr;
- bool cpu_boosted = true; /* start boosted */
+ /* |llllllllllllllll|rrrrrrrrrrrrrrrr| =>
+ * |mmmmmmmmmmmmmmmm|mmmmmmmmmmmmmmmm|
+ */
+ uint32_t *samp = (uint32_t *)&mfbuf[2*512];
+ uint32_t *samp_end = samp + samp_per_frame;
- /* Generic codec initialisation */
- ci = api;
-
-#ifdef USE_IRAM
- memcpy(iramstart, iramcopy, iramend - iramstart);
- memset(iedata, 0, iend - iedata);
-#endif
-
- if(ci->enc_get_inputs == NULL ||
- ci->enc_set_parameters == NULL ||
- ci->enc_alloc_chunk == NULL ||
- ci->enc_free_chunk == NULL ||
- ci->enc_wavbuf_near_empty == NULL ||
- ci->enc_get_wav_data == NULL ||
- ci->enc_set_header_callback == NULL )
- return CODEC_ERROR;
+ inline void to_mono(uint32_t **samp)
+ {
+ int32_t lr = **samp;
+ int32_t m = ((int16_t)lr + (lr >> 16)) >> 1;
+ *(*samp)++ = (m << 16) | (uint16_t)m;
+ } /* to_mono */
- ci->cpu_boost(true);
+ do
+ {
+ to_mono(&samp);
+ to_mono(&samp);
+ to_mono(&samp);
+ to_mono(&samp);
+ to_mono(&samp);
+ to_mono(&samp);
+ to_mono(&samp);
+ to_mono(&samp);
+ }
+ while (samp < samp_end);
+} /* to_mono_mm */
+
+#ifdef ROCKBOX_LITTLE_ENDIAN
+/* Swaps a frame to big endian */
+static inline void byte_swap_frame32(uint32_t *dst, uint32_t *src,
+ size_t size) ICODE_ATTR;
+static inline void byte_swap_frame32(uint32_t *dst, uint32_t *src,
+ size_t size)
+{
+ uint32_t *src_end = SKIPBYTES(src, size);
- *ci->enc_set_header_callback = NULL;
- ci->enc_get_inputs(&enc_buffer_size, &enc_channels, &enc_quality);
+ do
+ {
+ *dst++ = swap32(*src++);
+ *dst++ = swap32(*src++);
+ *dst++ = swap32(*src++);
+ *dst++ = swap32(*src++);
+ *dst++ = swap32(*src++);
+ *dst++ = swap32(*src++);
+ *dst++ = swap32(*src++);
+ *dst++ = swap32(*src++);
+ }
+ while(src < src_end);
+} /* byte_swap_frame32 */
+#endif /* ROCKBOX_LITTLE_ENDIAN */
- init_mp3_encoder_engine(enc_channels == 2, enc_quality, 44100);
+static void encode_frame(char *buffer, struct enc_chunk_hdr *chunk) ICODE_ATTR;
+static void encode_frame(char *buffer, struct enc_chunk_hdr *chunk)
+{
+ int gr, gr_cnt;
+ int max, min;
- /* must be 4byte aligned */
- chunk_size = (sizeof(long) + cfg.byte_per_frame + 1 + 3) & ~3;
- num_chunks = enc_buffer_size / chunk_size;
+ /* encode one mp3 frame in this loop */
+ CodedData.bitpos = 0;
+ memset(CodedData.bbuf, 0, sizeof(CodedData.bbuf));
- /* inform the main program about the buffer dimensions */
- ci->enc_set_parameters(chunk_size, num_chunks, SAMP_PER_FRAME,
- NULL, 0, AFMT_MPA_L3);
+ if((cfg.slot_lag += cfg.frac_per_frame) >= 64)
+ { /* Padding for this frame */
+ cfg.slot_lag -= 64;
+ cfg.mpg.padding = 1;
+ }
+ else
+ cfg.mpg.padding = 0;
-#ifdef CPU_COLDFIRE
- asm volatile ("move.l #0, %macsr"); /* integer mode */
-#endif
+ cfg.mean_bits = (8 * cfg.byte_per_frame + 8 * cfg.mpg.padding
+ - cfg.sideinfo_len) / cfg.granules / cfg.channels;
- /* main application waits for this flag during encoder loading */
- ci->enc_codec_loaded = true;
+ /* shift out old samples */
+ memcpy(mfbuf, mfbuf + 2*cfg.granules*576, 4*512);
- /* main encoding loop */
- while(!ci->stop_codec)
+ if (chunk->flags & CHUNKF_START_FILE)
{
- while((buffer = (long*)ci->enc_get_wav_data(SAMP_PER_FRAME*4)) != NULL)
- {
- if(ci->stop_codec)
- break;
-
- if(ci->enc_wavbuf_near_empty() == 0)
- {
- if(!cpu_boosted)
- {
- ci->cpu_boost(true);
- cpu_boosted = true;
- }
- }
+ /* prefix silent samples for encoder delay */
+ memset(mfbuf + 2*512, 0, ENC_DELAY_SIZE);
+ /* read new samples to iram for further processing */
+ memcpy(mfbuf + 2*512 + ENC_DELAY_SIZE/2,
+ buffer, pcm_chunk_size - ENC_DELAY_SIZE);
+ chunk->num_pcm = samp_per_frame - ENC_DELAY_SAMP;
+ }
+ else
+ {
+ /* read new samples to iram for further processing */
+ memcpy(mfbuf + 2*512, buffer, pcm_chunk_size);
+ chunk->num_pcm = samp_per_frame;
+ }
- /* encode one mp3 frame in this loop */
- CodedData.bitpos = 0;
- memset(CodedData.bbuf, 0, sizeof(CodedData.bbuf));
-
- if((cfg.slot_lag += cfg.frac_per_frame) >= 64)
- { /* Padding for this frame */
- cfg.slot_lag -= 64;
- cfg.mpg.padding = 1;
- }
- else
- cfg.mpg.padding = 0;
+ if (cfg.channels == 1)
+ to_mono_mm();
- cfg.mean_bits = (8 * cfg.byte_per_frame + 8 * cfg.mpg.padding
- - cfg.sideinfo_len) / cfg.granules / cfg.channels;
+ cfg.ResvSize = 0;
+ gr_cnt = cfg.granules * cfg.channels;
+ CodedData.bitpos = cfg.sideinfo_len; /* leave space for mp3 header */
- /* shift out old samples */
- memcpy(mfbuf, mfbuf + 2*cfg.granules*576, 4*512);
- /* read new samples to iram for further processing */
- memcpy((uint32*)(mfbuf + 2*512), buffer, 4*SAMP_PER_FRAME);
+ for(gr=0; gr<cfg.granules; gr++)
+ {
+ short *wk = mfbuf + 2*286 + gr*1152;
+ int ch;
- if(cfg.resample) /* downsample to half of original */
- for(i=2*512; i<2*512+2*SAMP_PER_FRAME; i+=4)
- {
- mfbuf[i/2+512] = (short)(((int)mfbuf[i+0] + mfbuf[i+2]) >> 1);
- mfbuf[i/2+513] = (short)(((int)mfbuf[i+1] + mfbuf[i+3]) >> 1);
- }
+ /* 16bit packed wav data can be windowed efficiently on coldfire */
+ window_subband1(wk, sb_data[0][1-gr][0], sb_data[1][1-gr][0]);
- if(cfg.channels == 1) /* mix left and right channels to mono */
- for(i=2*512; i<2*512+2*SAMP_PER_FRAME; i+=2)
- mfbuf[i] = mfbuf[i+1] = (short)(((int)mfbuf[i] + mfbuf[i+1]) >> 1);
+ for(ch=0; ch<cfg.channels; ch++)
+ {
+ int ii, k, shift;
- cfg.ResvSize = 0;
- gr_cnt = cfg.granules * cfg.channels;
- CodedData.bitpos = cfg.sideinfo_len; /* leave space for mp3 header */
+ wk = mfbuf + 2*286 + gr*1152 + ch;
- for(gr=0; gr<cfg.granules; gr++)
+ /* 36864=4*18*16*32 */
+ for(k=0; k<18; k++, wk+=64)
{
- short *wk = mfbuf + 2*286 + gr*1152;
-
- /* 16bit packed wav data can be windowed efficiently on coldfire */
- window_subband1(wk, sb_data[0][1-gr][0], sb_data[1][1-gr][0]);
-
- for(ch=0; ch<cfg.channels; ch++)
- {
- int band;
- int *mdct;
-
- wk = mfbuf + 2*286 + gr*1152 + ch;
-
- /* 36864=4*18*16*32 */
- for(k=0; k<18; k++, wk+=64)
+ window_subband2(wk, sb_data[ch][1-gr][k]);
+ /* Compensate for inversion in the analysis filter */
+ if(k & 1)
{
- window_subband2(wk, sb_data[ch][1-gr][k]);
- /* Compensate for inversion in the analysis filter */
- if(k & 1)
+ int band;
for(band=1; band<32; band+=2)
- sb_data[ch][1-gr][k][band] *= -1;
+ sb_data[ch][1-gr][k][band] *= -1;
}
+ }
- /* Perform imdct of 18 previous + 18 current subband samples */
- /* for integer precision do this loop twice (if neccessary) */
- shift = k = 14;
- for(ii=0; ii<2 && k; ii++)
+ /* Perform imdct of 18 previous + 18 current subband samples
+ for integer precision do this loop twice (if neccessary)
+ */
+ shift = k = 14;
+ for(ii=0; ii<2 && k; ii++)
+ {
+ int *mdct = mdct_freq;
+ int band;
+
+ cfg.cod_info[gr][ch].additStep = 4 * (14 - shift);
+
+ for(band=0; band<cfg.mpg.num_bands; band++, mdct+=18)
{
- mdct = mdct_freq;
- cfg.cod_info[gr][ch].additStep = 4 * (14 - shift);
- for(band=0; band<cfg.mpg.num_bands; band++, mdct+=18)
- {
int *band0 = sb_data[ch][ gr][0] + order[band];
int *band1 = sb_data[ch][1-gr][0] + order[band];
int work[18];
@@ -2176,16 +2200,20 @@ enum codec_status codec_start(struct codec_api* api)
/* 9216=4*32*9*8 */
for(k=-9; k<0; k++)
{
- int a = shft_n(band1[(k+9)*32], shift);
- int b = shft_n(band1[(8-k)*32], shift);
- int c = shft_n(band0[(k+9)*32], shift);
- int d = shft_n(band0[(8-k)*32], shift);
-
- work[k+ 9] = shft16(a * win[k+ 9][0] + b * win[k+ 9][1]
- + c * win[k+ 9][2] + d * win[k+ 9][3]);
-
- work[k+18] = shft16(c * win[k+18][0] + d * win[k+18][1]
- + a * win[k+18][2] + b * win[k+18][3]);
+ int a = shft_n(band1[(k+9)*32], shift);
+ int b = shft_n(band1[(8-k)*32], shift);
+ int c = shft_n(band0[(k+9)*32], shift);
+ int d = shft_n(band0[(8-k)*32], shift);
+
+ work[k+ 9] = shft16(a * win[k+ 9][0] +
+ b * win[k+ 9][1] +
+ c * win[k+ 9][2] +
+ d * win[k+ 9][3]);
+
+ work[k+18] = shft16(c * win[k+18][0] +
+ d * win[k+18][1] +
+ a * win[k+18][2] +
+ b * win[k+18][3]);
}
/* 7200=4*18*100 */
@@ -2193,67 +2221,309 @@ enum codec_status codec_start(struct codec_api* api)
/* Perform aliasing reduction butterfly */
if(band != 0)
- for(k=7; k>=0; --k)
- {
- int bu, bd;
- bu = shft15(mdct[k]) * ca[k] + shft15(mdct[-1-k]) * cs[k];
- bd = shft15(mdct[k]) * cs[k] - shft15(mdct[-1-k]) * ca[k];
- mdct[-1-k] = bu;
- mdct[ k ] = bd;
- }
- }
-
- max = min = 0;
- for(k=0; k<576; k++)
- {
+ {
+ for(k=7; k>=0; --k)
+ {
+ int bu, bd;
+ bu = shft15(mdct[k]) * ca[k] +
+ shft15(mdct[-1-k]) * cs[k];
+ bd = shft15(mdct[k]) * cs[k] -
+ shft15(mdct[-1-k]) * ca[k];
+ mdct[-1-k] = bu;
+ mdct[ k ] = bd;
+ }
+ }
+ }
+
+ max = min = 0;
+ for(k=0; k<576; k++)
+ {
mdct_freq[k] = shft13(mdct_freq[k]);
if(max < mdct_freq[k]) max = mdct_freq[k];
if(min > mdct_freq[k]) min = mdct_freq[k];
- }
+ }
- max = (max > -min) ? max : -min;
- cfg.cod_info[gr][ch].max_val = (long)max;
+ max = (max > -min) ? max : -min;
+ cfg.cod_info[gr][ch].max_val = (long)max;
- /* calc new shift for higher integer precision */
- for(k=0; max<(0x3c00>>k); k++);
+ /* calc new shift for higher integer precision */
+ for(k=0; max<(0x3c00>>k); k++);
shift = 12 - k;
- }
+ }
- cfg.cod_info[gr][ch].quantStep += cfg.cod_info[gr][ch].additStep;
+ cfg.cod_info[gr][ch].quantStep +=
+ cfg.cod_info[gr][ch].additStep;
- /* bit and noise allocation */
- iteration_loop(mdct_freq, &cfg.cod_info[gr][ch], gr_cnt--);
- /* write the frame to the bitstream */
- Huffmancodebits(enc_data, mdct_freq, &cfg.cod_info[gr][ch]);
+ /* bit and noise allocation */
+ iteration_loop(mdct_freq, &cfg.cod_info[gr][ch],
+ gr_cnt--);
+ /* write the frame to the bitstream */
+ Huffmancodebits(enc_data, mdct_freq,
+ &cfg.cod_info[gr][ch]);
- cfg.cod_info[gr][ch].quantStep -= cfg.cod_info[gr][ch].additStep;
+ cfg.cod_info[gr][ch].quantStep -=
+ cfg.cod_info[gr][ch].additStep;
- if(cfg.granules == 1)
- memcpy(sb_data[ch][0], sb_data[ch][1], sizeof(sb_data[ch][0]));
- }
+ if(cfg.granules == 1)
+ {
+ memcpy(sb_data[ch][0], sb_data[ch][1],
+ sizeof(sb_data[ch][0]));
}
+ }
+ }
+
+ chunk->enc_size = cfg.byte_per_frame + cfg.mpg.padding;
- mp3_chunk_ptr = (uint32*)ci->enc_alloc_chunk();
- mp3_chunk_ptr[0] = cfg.byte_per_frame + cfg.mpg.padding; //(CodedData.bitpos + 7) >> 3;
/* finish this chunk by adding sideinfo header data */
CodedData.bitpos = 0;
encodeSideInfo( cfg.cod_info );
- /* allocate mp3 chunk, set chunk size, copy chunk to enc_buffer */
- memcpy(&mp3_chunk_ptr[1], CodedData.bbuf, mp3_chunk_ptr[0]);
- ci->enc_free_chunk();
+#ifdef ROCKBOX_BIG_ENDIAN
+ /* copy chunk to enc_buffer */
+ memcpy(chunk->enc_data, CodedData.bbuf, chunk->enc_size);
+#else
+ /* swap frame to big endian */
+ byte_swap_frame32(chunk->enc_data, CodedData.bbuf, chunk->enc_size);
+#endif
+} /* encode_frame */
+
+/* called very often - inline */
+static inline bool is_file_data_ok(struct enc_file_event_data *filed) ICODE_ATTR;
+static inline bool is_file_data_ok(struct enc_file_event_data *filed)
+{
+ return filed->rec_file >= 0 && (long)filed->chunk->flags >= 0;
+} /* is_event_ok */
- ci->yield();
+/* called very often - inline */
+static inline bool on_write_chunk(struct enc_file_event_data *data) ICODE_ATTR;
+static inline bool on_write_chunk(struct enc_file_event_data *data)
+{
+ if (!is_file_data_ok(data))
+ return false;
+
+ if (data->chunk->enc_data == NULL)
+ {
+#ifdef ROCKBOX_HAS_LOGF
+ ci->logf("mp3 enc: NULL data");
+#endif
+ return true;
+ }
+
+ if (ci->write(data->rec_file, data->chunk->enc_data,
+ data->chunk->enc_size) != (ssize_t)data->chunk->enc_size)
+ return false;
+
+ data->num_pcm_samples += data->chunk->num_pcm;
+ return true;
+} /* on_write_chunk */
+
+static bool on_start_file(struct enc_file_event_data *data)
+{
+ if ((data->chunk->flags & CHUNKF_ERROR) || *data->filename == '\0')
+ return false;
+
+ data->rec_file = ci->open(data->filename, O_RDWR|O_CREAT|O_TRUNC);
+
+ if (data->rec_file < 0)
+ return false;
+
+ /* reset sample count */
+ data->num_pcm_samples = 0;
+ return true;
+} /* on_start_file */
+
+static bool on_end_file(struct enc_file_event_data *data)
+{
+ if (!is_file_data_ok(data))
+ return false;
+
+ ci->fsync(data->rec_file);
+ ci->close(data->rec_file);
+ data->rec_file = -1;
+
+ return true;
+} /* on_end_file */
+
+static void on_rec_new_stream(struct enc_buffer_event_data *data)
+{
+ int num_frames = cfg.mpg.type == 1 ?
+ ENC_PADDING_FRAMES1 : ENC_PADDING_FRAMES2;
+
+ if (data->flags & CHUNKF_END_FILE)
+ {
+ /* add silent frames to end - encoder will also be flushed for start
+ of next file if any */
+ memset(res_buffer, 0, pcm_chunk_size);
+
+ /* the initial chunk given for the end is at enc_wr_index */
+ while (num_frames-- > 0)
+ {
+ data->chunk->enc_data = ENC_CHUNK_SKIP_HDR(data->chunk->enc_data,
+ data->chunk);
+
+ encode_frame(res_buffer, data->chunk);
+ data->chunk->num_pcm = samp_per_frame;
+
+ ci->enc_finish_chunk();
+ data->chunk = ci->enc_get_chunk();
}
+ }
+ else if (data->flags & CHUNKF_PRERECORD)
+ {
+ /* nothing to add and we cannot change prerecorded data */
+ }
+ else if (data->flags & CHUNKF_START_FILE)
+ {
+ /* starting fresh ... be sure to flush encoder first */
+ struct enc_chunk_hdr *chunk = ENC_CHUNK_HDR(res_buffer);
- if(ci->enc_wavbuf_near_empty())
+ chunk->flags = 0;
+ chunk->enc_data = ENC_CHUNK_SKIP_HDR(chunk->enc_data, chunk);
+
+ while (num_frames-- > 0)
{
- if(cpu_boosted)
+ memset(chunk->enc_data, 0, pcm_chunk_size);
+ encode_frame(chunk->enc_data, chunk);
+ }
+ }
+} /* on_rec_new_stream */
+
+static void enc_events_callback(enum enc_events event, void *data) ICODE_ATTR;
+static void enc_events_callback(enum enc_events event, void *data)
+{
+ if (event == ENC_WRITE_CHUNK)
+ {
+ if (on_write_chunk((struct enc_file_event_data *)data))
+ return;
+ }
+ else if (event == ENC_START_FILE)
+ {
+ if (on_start_file((struct enc_file_event_data *)data))
+ return;
+ }
+ else if (event == ENC_END_FILE)
+ {
+ if (on_end_file((struct enc_file_event_data *)data))
+ return;
+ }
+ else if (event == ENC_REC_NEW_STREAM)
+ {
+ on_rec_new_stream((struct enc_buffer_event_data *)data);
+ return;
+ }
+ else
+ {
+ return;
+ }
+
+ ((struct enc_file_event_data *)data)->chunk->flags |= CHUNKF_ERROR;
+} /* enc_events_callback */
+
+static bool enc_init(void)
+{
+ struct enc_inputs inputs;
+ struct enc_parameters params;
+
+ if (ci->enc_get_inputs == NULL ||
+ ci->enc_set_parameters == NULL ||
+ ci->enc_get_chunk == NULL ||
+ ci->enc_finish_chunk == NULL ||
+ ci->enc_pcm_buf_near_empty == NULL ||
+ ci->enc_get_pcm_data == NULL ||
+ ci->enc_unget_pcm_data == NULL )
+ return false;
+
+ ci->enc_get_inputs(&inputs);
+
+ if (inputs.config->afmt != AFMT_MPA_L3)
+ return false;
+
+ init_mp3_encoder_engine(inputs.sample_rate, inputs.num_channels,
+ inputs.config);
+
+ /* configure the buffer system */
+ params.afmt = AFMT_MPA_L3;
+ params.chunk_size = cfg.byte_per_frame + 1;
+ params.enc_sample_rate = cfg.samplerate;
+ /* need enough reserved bytes to hold one frame of pcm samples + hdr
+ for padding and flushing */
+ params.reserve_bytes = ENC_CHUNK_HDR_SIZE + pcm_chunk_size;
+ params.events_callback = enc_events_callback;
+ ci->enc_set_parameters(&params);
+
+ res_buffer = params.reserve_buffer;
+
+#ifdef CPU_COLDFIRE
+ asm volatile ("move.l #0, %macsr"); /* integer mode */
+#endif
+
+ return true;
+} /* enc_init */
+
+enum codec_status codec_start(struct codec_api* api)
+{
+ bool cpu_boosted;
+
+ /* Generic codec initialisation */
+ ci = api;
+
+#ifdef USE_IRAM
+ memcpy(iramstart, iramcopy, iramend - iramstart);
+ memset(iedata, 0, iend - iedata);
+#endif
+
+ if (!enc_init())
+ {
+ ci->enc_codec_loaded = -1;
+ return CODEC_ERROR;
+ }
+
+ /* main application waits for this flag during encoder loading */
+ ci->enc_codec_loaded = 1;
+
+ ci->cpu_boost(true);
+ cpu_boosted = true;
+
+ /* main encoding loop */
+ while (!ci->stop_codec)
+ {
+ char *buffer;
+
+ while ((buffer = ci->enc_get_pcm_data(pcm_chunk_size)) != NULL)
+ {
+ struct enc_chunk_hdr *chunk;
+
+ if (ci->stop_codec)
+ break;
+
+ if (!cpu_boosted && ci->enc_pcm_buf_near_empty() == 0)
+ {
+ ci->cpu_boost(true);
+ cpu_boosted = true;
+ }
+
+ chunk = ci->enc_get_chunk();
+ chunk->enc_data = ENC_CHUNK_SKIP_HDR(chunk->enc_data, chunk);
+
+ encode_frame(buffer, chunk);
+
+ if (chunk->num_pcm < samp_per_frame)
+ {
+ ci->enc_unget_pcm_data(pcm_chunk_size - chunk->num_pcm*4);
+ chunk->num_pcm = samp_per_frame;
+ }
+
+ ci->enc_finish_chunk();
+
+ ci->yield();
+ }
+
+ if (cpu_boosted && ci->enc_pcm_buf_near_empty())
{
ci->cpu_boost(false);
cpu_boosted = false;
}
- }
+
ci->yield();
}
@@ -2261,12 +2531,12 @@ enum codec_status codec_start(struct codec_api* api)
ci->cpu_boost(false);
/* reset parameters to initial state */
- ci->enc_set_parameters(0, 0, 0, 0, 0, 0);
+ ci->enc_set_parameters(NULL);
/* main application waits for this flag during encoder removing */
- ci->enc_codec_loaded = false;
+ ci->enc_codec_loaded = 0;
return CODEC_OK;
-}
+} /* codec_start */
-#endif
+#endif /* ndef SIMULATOR */
diff --git a/apps/codecs/wav_enc.c b/apps/codecs/wav_enc.c
index 5aabb5d..974a903 100644
--- a/apps/codecs/wav_enc.c
+++ b/apps/codecs/wav_enc.c
@@ -19,140 +19,364 @@
#ifndef SIMULATOR
+#include <inttypes.h>
#include "codeclib.h"
-CODEC_HEADER
+CODEC_ENC_HEADER
+
+#ifdef USE_IRAM
+extern char iramcopy[];
+extern char iramstart[];
+extern char iramend[];
+extern char iedata[];
+extern char iend[];
+#endif
+
+struct riff_header
+{
+ uint8_t riff_id[4]; /* 00h - "RIFF" */
+ uint32_t riff_size; /* 04h - sz following headers + data_size */
+ /* format header */
+ uint8_t format[4]; /* 08h - "WAVE" */
+ uint8_t format_id[4]; /* 0Ch - "fmt " */
+ uint32_t format_size; /* 10h - 16 for PCM (sz format data) */
+ /* format data */
+ uint16_t audio_format; /* 14h - 1=PCM */
+ uint16_t num_channels; /* 16h - 1=M, 2=S, etc. */
+ uint32_t sample_rate; /* 18h - HZ */
+ uint32_t byte_rate; /* 1Ch - num_channels*sample_rate*bits_per_sample/8 */
+ uint16_t block_align; /* 20h - num_channels*bits_per_samples/8 */
+ uint16_t bits_per_sample; /* 22h - 8=8 bits, 16=16 bits, etc. */
+ /* Not for audio_format=1 (PCM) */
+/* unsigned short extra_param_size; 24h - size of extra data */
+/* unsigned char *extra_params; */
+ /* data header */
+ uint8_t data_id[4]; /* 24h - "data" */
+ uint32_t data_size; /* 28h - num_samples*num_channels*bits_per_sample/8 */
+/* unsigned char *data; 2ch - actual sound data */
+};
+
+#define RIFF_FMT_HEADER_SIZE 12 /* format -> format_size */
+#define RIFF_FMT_DATA_SIZE 16 /* audio_format -> bits_per_sample */
+#define RIFF_DATA_HEADER_SIZE 8 /* data_id -> data_size */
+
+#define PCM_DEPTH_BYTES 2
+#define PCM_DEPTH_BITS 16
+#define PCM_SAMP_PER_CHUNK 2048
+#define PCM_CHUNK_SIZE (PCM_SAMP_PER_CHUNK*4)
static struct codec_api *ci;
-static int enc_channels;
+static int num_channels;
+uint32_t sample_rate;
+uint32_t enc_size;
-#define CHUNK_SIZE 8192
+static const struct riff_header riff_header =
+{
+ /* "RIFF" header */
+ { 'R', 'I', 'F', 'F' }, /* riff_id */
+ 0, /* riff_size (*) */
+ /* format header */
+ { 'W', 'A', 'V', 'E' }, /* format */
+ { 'f', 'm', 't', ' ' }, /* format_id */
+ H_TO_LE32(16), /* format_size */
+ /* format data */
+ H_TO_LE16(1), /* audio_format */
+ 0, /* num_channels (*) */
+ 0, /* sample_rate (*) */
+ 0, /* byte_rate (*) */
+ 0, /* block_align (*) */
+ H_TO_LE16(PCM_DEPTH_BITS), /* bits_per_sample */
+ /* data header */
+ { 'd', 'a', 't', 'a' }, /* data_id */
+ 0 /* data_size (*) */
+ /* (*) updated during ENC_END_FILE event */
+};
-static unsigned char wav_header[44] =
-{'R','I','F','F',0,0,0,0,'W','A','V','E','f','m','t',' ',16,
- 0,0,0,1,0,2,0,0x44,0xac,0,0,0x10,0xb1,2,0,4,0,16,0,'d','a','t','a',0,0,0,0};
+/* called version often - inline */
+static inline bool is_file_data_ok(struct enc_file_event_data *data) ICODE_ATTR;
+static inline bool is_file_data_ok(struct enc_file_event_data *data)
+{
+ return data->rec_file >= 0 && (long)data->chunk->flags >= 0;
+} /* is_file_data_ok */
-static unsigned char wav_header_mono[44] =
-{'R','I','F','F',0,0,0,0,'W','A','V','E','f','m','t',' ',16,
- 0,0,0,1,0,1,0,0x44,0xac,0,0,0x88,0x58,1,0,2,0,16,0,'d','a','t','a',0,0,0,0};
+/* called version often - inline */
+static inline bool on_write_chunk(struct enc_file_event_data *data) ICODE_ATTR;
+static inline bool on_write_chunk(struct enc_file_event_data *data)
+{
+ if (!is_file_data_ok(data))
+ return false;
-/* update file header info callback function (called by main application) */
-void enc_set_header(void *head_buffer, /* ptr to the file header data */
- int head_size, /* size of this header data */
- int num_pcm_samples, /* amount of processed pcm samples */
- bool is_file_header)
+ if (data->chunk->enc_data == NULL)
+ {
+#ifdef ROCKBOX_HAS_LOGF
+ ci->logf("wav enc: NULL data");
+#endif
+ return true;
+ }
+
+ if (ci->write(data->rec_file, data->chunk->enc_data,
+ data->chunk->enc_size) != (ssize_t)data->chunk->enc_size)
+ return false;
+
+ data->num_pcm_samples += data->chunk->num_pcm;
+ return true;
+} /* on_write_chunk */
+
+static bool on_start_file(struct enc_file_event_data *data)
{
- int num_file_bytes = num_pcm_samples * 2 * enc_channels;
+ if ((data->chunk->flags & CHUNKF_ERROR) || *data->filename == '\0')
+ return false;
+
+ data->rec_file = ci->open(data->filename, O_RDWR|O_CREAT|O_TRUNC);
+
+ if (data->rec_file < 0)
+ return false;
+
+ /* reset sample count */
+ data->num_pcm_samples = 0;
- if(is_file_header)
+ /* write template header */
+ if (ci->write(data->rec_file, &riff_header, sizeof (riff_header))
+ != sizeof (riff_header))
{
- /* update file header before file closing */
- if((int)sizeof(wav_header) < head_size)
+ return false;
+ }
+
+ data->new_enc_size += sizeof (riff_header);
+ return true;
+} /* on_start_file */
+
+static bool on_end_file(struct enc_file_event_data *data)
+{
+ /* update template header */
+ struct riff_header hdr;
+ uint32_t data_size;
+
+ if (!is_file_data_ok(data))
+ return false;
+
+ if (ci->lseek(data->rec_file, 0, SEEK_SET) != 0 ||
+ ci->read(data->rec_file, &hdr, sizeof (hdr)) != sizeof (hdr))
+ {
+ return false;
+ }
+
+ data_size = data->num_pcm_samples*num_channels*PCM_DEPTH_BYTES;
+
+ /* "RIFF" header */
+ hdr.riff_size = htole32(RIFF_FMT_HEADER_SIZE + RIFF_FMT_DATA_SIZE
+ + RIFF_DATA_HEADER_SIZE + data_size);
+
+ /* format data */
+ hdr.num_channels = htole16(num_channels);
+ hdr.sample_rate = htole32(sample_rate);
+ hdr.byte_rate = htole32(sample_rate*num_channels* PCM_DEPTH_BYTES);
+ hdr.block_align = htole16(num_channels*PCM_DEPTH_BYTES);
+
+ /* data header */
+ hdr.data_size = htole32(data_size);
+
+ if (ci->lseek(data->rec_file, 0, SEEK_SET) != 0 ||
+ ci->write(data->rec_file, &hdr, sizeof (hdr)) != sizeof (hdr))
+ {
+ return false;
+ }
+
+ ci->fsync(data->rec_file);
+ ci->close(data->rec_file);
+ data->rec_file = -1;
+
+ return true;
+} /* on_end_file */
+
+static void enc_events_callback(enum enc_events event, void *data) ICODE_ATTR;
+static void enc_events_callback(enum enc_events event, void *data)
+{
+ if (event == ENC_WRITE_CHUNK)
+ {
+ if (on_write_chunk((struct enc_file_event_data *)data))
+ return;
+ }
+ else if (event == ENC_START_FILE)
+ {
+ if (on_start_file((struct enc_file_event_data *)data))
+ return;
+ }
+ else if (event == ENC_END_FILE)
+ {
+ if (on_end_file((struct enc_file_event_data *)data))
+ return;
+ }
+ else
+ {
+ return;
+ }
+
+ ((struct enc_file_event_data *)data)->chunk->flags |= CHUNKF_ERROR;
+} /* enc_events_callback */
+
+/* convert native pcm samples to wav format samples */
+static void chunk_to_wav_format(uint32_t *src, uint32_t *dst) ICODE_ATTR;
+static void chunk_to_wav_format(uint32_t *src, uint32_t *dst)
+{
+ if (num_channels == 1)
+ {
+ /* On big endian:
+ * |LLLLLLLLllllllll|RRRRRRRRrrrrrrrr|
+ * |LLLLLLLLllllllll|RRRRRRRRrrrrrrrr| =>
+ * |mmmmmmmmMMMMMMMM|mmmmmmmmMMMMMMMM|
+ *
+ * On little endian:
+ * |llllllllLLLLLLLL|rrrrrrrrRRRRRRRR|
+ * |llllllllLLLLLLLL|rrrrrrrrRRRRRRRR| =>
+ * |mmmmmmmmMMMMMMMM|mmmmmmmmMMMMMMMM|
+ */
+ uint32_t *src_end = src + PCM_SAMP_PER_CHUNK;
+
+ inline void to_mono(uint32_t **src, uint32_t **dst)
{
- /* update wave header size entries: special to WAV format */
- *(long*)(head_buffer+ 4) = htole32(num_file_bytes + 36);
- *(long*)(head_buffer+40) = htole32(num_file_bytes);
+ int32_t lr1, lr2;
+
+ lr1 = *(*src)++;
+ lr1 = ((int16_t)lr1 + (lr1 >> 16)) >> 1;
+
+ lr2 = *(*src)++;
+ lr2 = ((int16_t)lr2 + (lr2 >> 16)) >> 1;
+ *(*dst)++ = swap_odd_even_be32((lr1 << 16) | (uint16_t)lr2);
+ } /* to_mono */
+
+ do
+ {
+ to_mono(&src, &dst);
+ to_mono(&src, &dst);
+ to_mono(&src, &dst);
+ to_mono(&src, &dst);
+ to_mono(&src, &dst);
+ to_mono(&src, &dst);
+ to_mono(&src, &dst);
+ to_mono(&src, &dst);
}
+ while (src < src_end);
}
-}
+ else
+ {
+#ifdef ROCKBOX_BIG_ENDIAN
+ /* |LLLLLLLLllllllll|RRRRRRRRrrrrrrrr| =>
+ * |llllllllLLLLLLLL|rrrrrrrrRRRRRRRR|
+ */
+ uint32_t *src_end = src + PCM_SAMP_PER_CHUNK;
-/* main codec entry point */
-enum codec_status codec_start(struct codec_api* api)
+ do
+ {
+ *dst++ = swap_odd_even32(*src++);
+ *dst++ = swap_odd_even32(*src++);
+ *dst++ = swap_odd_even32(*src++);
+ *dst++ = swap_odd_even32(*src++);
+ *dst++ = swap_odd_even32(*src++);
+ *dst++ = swap_odd_even32(*src++);
+ *dst++ = swap_odd_even32(*src++);
+ *dst++ = swap_odd_even32(*src++);
+ }
+ while (src < src_end);
+#else
+ /* |llllllllLLLLLLLL|rrrrrrrrRRRRRRRR| =>
+ * |llllllllLLLLLLLL|rrrrrrrrRRRRRRRR|
+ */
+ ci->memcpy(dst, src, PCM_CHUNK_SIZE);
+#endif
+ }
+} /* chunk_to_wav_format */
+
+static bool init_encoder(void)
{
- int i;
- long lr;
- unsigned long t;
- unsigned long *src;
- unsigned long *dst;
- int chunk_size, num_chunks, samp_per_chunk;
- int enc_buffer_size;
- int enc_quality;
- bool cpu_boosted = true; /* start boosted */
+ struct enc_inputs inputs;
+ struct enc_parameters params;
- ci = api; // copy to global api pointer
+ if (ci->enc_get_inputs == NULL ||
+ ci->enc_set_parameters == NULL ||
+ ci->enc_get_chunk == NULL ||
+ ci->enc_finish_chunk == NULL ||
+ ci->enc_pcm_buf_near_empty == NULL ||
+ ci->enc_get_pcm_data == NULL )
+ return false;
- if(ci->enc_get_inputs == NULL ||
- ci->enc_set_parameters == NULL ||
- ci->enc_alloc_chunk == NULL ||
- ci->enc_free_chunk == NULL ||
- ci->enc_wavbuf_near_empty == NULL ||
- ci->enc_get_wav_data == NULL ||
- ci->enc_set_header_callback == NULL )
- return CODEC_ERROR;
+ ci->enc_get_inputs(&inputs);
- ci->cpu_boost(true);
+ if (inputs.config->afmt != AFMT_PCM_WAV)
+ return false;
- *ci->enc_set_header_callback = enc_set_header;
- ci->enc_get_inputs(&enc_buffer_size, &enc_channels, &enc_quality);
+ sample_rate = inputs.sample_rate;
+ num_channels = inputs.num_channels;
/* configure the buffer system */
- chunk_size = sizeof(long) + CHUNK_SIZE * enc_channels / 2;
- num_chunks = enc_buffer_size / chunk_size;
- samp_per_chunk = CHUNK_SIZE / 4;
+ params.afmt = AFMT_PCM_WAV;
+ enc_size = PCM_CHUNK_SIZE*inputs.num_channels / 2;
+ params.chunk_size = enc_size;
+ params.enc_sample_rate = sample_rate;
+ params.reserve_bytes = 0;
+ params.events_callback = enc_events_callback;
+ ci->enc_set_parameters(&params);
+
+ return true;
+} /* init_encoder */
+
+/* main codec entry point */
+enum codec_status codec_start(struct codec_api* api)
+{
+ bool cpu_boosted;
- /* inform the main program about buffer dimensions and other params */
- ci->enc_set_parameters(chunk_size, num_chunks, samp_per_chunk,
- (enc_channels == 2) ? wav_header : wav_header_mono,
- sizeof(wav_header), AFMT_PCM_WAV);
+ ci = api; // copy to global api pointer
+
+#ifdef USE_IRAM
+ ci->memcpy(iramstart, iramcopy, iramend - iramstart);
+ ci->memset(iedata, 0, iend - iedata);
+#endif
+
+ if (!init_encoder())
+ {
+ ci->enc_codec_loaded = -1;
+ return CODEC_ERROR;
+ }
/* main application waits for this flag during encoder loading */
- ci->enc_codec_loaded = true;
+ ci->enc_codec_loaded = 1;
+
+ ci->cpu_boost(true);
+ cpu_boosted = true;
/* main encoding loop */
while(!ci->stop_codec)
{
- while((src = (unsigned long*)ci->enc_get_wav_data(CHUNK_SIZE)) != NULL)
+ uint32_t *src;
+
+ while ((src = (uint32_t *)ci->enc_get_pcm_data(PCM_CHUNK_SIZE)) != NULL)
{
- if(ci->stop_codec)
+ struct enc_chunk_hdr *chunk;
+
+ if (ci->stop_codec)
break;
- if(ci->enc_wavbuf_near_empty() == 0)
+ if (!cpu_boosted && ci->enc_pcm_buf_near_empty() == 0)
{
- if(!cpu_boosted)
- {
- ci->cpu_boost(true);
- cpu_boosted = true;
- }
+ ci->cpu_boost(true);
+ cpu_boosted = true;
}
- dst = (unsigned long*)ci->enc_alloc_chunk();
- *dst++ = CHUNK_SIZE * enc_channels / 2; /* set size info */
+ chunk = ci->enc_get_chunk();
+ chunk->enc_size = enc_size;
+ chunk->num_pcm = PCM_SAMP_PER_CHUNK;
+ chunk->enc_data = ENC_CHUNK_SKIP_HDR(chunk->enc_data, chunk);
- if(enc_channels == 2)
- {
- /* swap byte order & copy to destination */
- for (i=0; i<CHUNK_SIZE/4; i++)
- {
- t = *src++;
- *dst++ = ((t >> 8) & 0xff00ff) | ((t << 8) & 0xff00ff00);
- }
- }
- else
- {
- /* mix left/right, swap byte order & copy to destination */
- for (i=0; i<CHUNK_SIZE/8; i++)
- {
- lr = (long)*src++;
- lr = (((lr<<16)>>16) + (lr>>16)) >> 1; /* left+right */
- t = (lr << 16);
- lr = (long)*src++;
- lr = (((lr<<16)>>16) + (lr>>16)) >> 1; /* left+right */
- t |= lr & 0xffff;
- *dst++ = ((t >> 8) & 0xff00ff) | ((t << 8) & 0xff00ff00);
- }
- }
+ chunk_to_wav_format(src, (uint32_t *)chunk->enc_data);
- ci->enc_free_chunk();
+ ci->enc_finish_chunk();
ci->yield();
}
- if(ci->enc_wavbuf_near_empty())
+ if (cpu_boosted && ci->enc_pcm_buf_near_empty() != 0)
{
- if(cpu_boosted)
- {
- ci->cpu_boost(false);
- cpu_boosted = false;
- }
+ ci->cpu_boost(false);
+ cpu_boosted = false;
}
ci->yield();
@@ -162,11 +386,12 @@ enum codec_status codec_start(struct codec_api* api)
ci->cpu_boost(false);
/* reset parameters to initial state */
- ci->enc_set_parameters(0, 0, 0, 0, 0, 0);
+ ci->enc_set_parameters(NULL);
/* main application waits for this flag during encoder removing */
- ci->enc_codec_loaded = false;
+ ci->enc_codec_loaded = 0;
return CODEC_OK;
-}
-#endif
+} /* codec_start */
+
+#endif /* ndef SIMULATOR */
diff --git a/apps/codecs/wavpack_enc.c b/apps/codecs/wavpack_enc.c
index eced7f1..5318abc 100644
--- a/apps/codecs/wavpack_enc.c
+++ b/apps/codecs/wavpack_enc.c
@@ -22,201 +22,474 @@
#include "codeclib.h"
#include "libwavpack/wavpack.h"
-CODEC_HEADER
+CODEC_ENC_HEADER
+
+#ifdef USE_IRAM
+extern char iramcopy[];
+extern char iramstart[];
+extern char iramend[];
+extern char iedata[];
+extern char iend[];
+#endif
-typedef unsigned long uint32;
-typedef unsigned short uint16;
-typedef unsigned char uint8;
+/** Types **/
+typedef struct
+{
+ uint8_t type; /* Type of metadata */
+ uint8_t word_size; /* Size of metadata in words */
+} WavpackMetadataHeader;
-static unsigned char wav_header_ster [46] =
-{33,22,'R','I','F','F',0,0,0,0,'W','A','V','E','f','m','t',' ',16,
- 0,0,0,1,0,2,0,0x44,0xac,0,0,0x10,0xb1,2,0,4,0,16,0,'d','a','t','a',0,0,0,0};
+struct riff_header
+{
+ uint8_t riff_id[4]; /* 00h - "RIFF" */
+ uint32_t riff_size; /* 04h - sz following headers + data_size */
+ /* format header */
+ uint8_t format[4]; /* 08h - "WAVE" */
+ uint8_t format_id[4]; /* 0Ch - "fmt " */
+ uint32_t format_size; /* 10h - 16 for PCM (sz format data) */
+ /* format data */
+ uint16_t audio_format; /* 14h - 1=PCM */
+ uint16_t num_channels; /* 16h - 1=M, 2=S, etc. */
+ uint32_t sample_rate; /* 18h - HZ */
+ uint32_t byte_rate; /* 1Ch - num_channels*sample_rate*bits_per_sample/8 */
+ uint16_t block_align; /* 20h - num_channels*bits_per_samples/8 */
+ uint16_t bits_per_sample; /* 22h - 8=8 bits, 16=16 bits, etc. */
+ /* Not for audio_format=1 (PCM) */
+/* unsigned short extra_param_size; 24h - size of extra data */
+/* unsigned char *extra_params; */
+ /* data header */
+ uint8_t data_id[4]; /* 24h - "data" */
+ uint32_t data_size; /* 28h - num_samples*num_channels*bits_per_sample/8 */
+/* unsigned char *data; 2ch - actual sound data */
+};
+
+#define RIFF_FMT_HEADER_SIZE 12 /* format -> format_size */
+#define RIFF_FMT_DATA_SIZE 16 /* audio_format -> bits_per_sample */
+#define RIFF_DATA_HEADER_SIZE 8 /* data_id -> data_size */
+
+#define PCM_DEPTH_BITS 16
+#define PCM_DEPTH_BYTES 2
+#define PCM_SAMP_PER_CHUNK 5000
+#define PCM_CHUNK_SIZE (4*PCM_SAMP_PER_CHUNK)
+
+/** Data **/
+static struct codec_api *ci;
+static int8_t input_buffer[PCM_CHUNK_SIZE*2] IBSS_ATTR;
+static WavpackConfig config IBSS_ATTR;
+static WavpackContext *wpc;
+static int32_t data_size, input_size, input_step IBSS_ATTR;
-static unsigned char wav_header_mono [46] =
-{33,22,'R','I','F','F',0,0,0,0,'W','A','V','E','f','m','t',' ',16,
- 0,0,0,1,0,1,0,0x44,0xac,0,0,0x88,0x58,1,0,2,0,16,0,'d','a','t','a',0,0,0,0};
+static const WavpackMetadataHeader wvpk_mdh =
+{
+ ID_RIFF_HEADER,
+ sizeof (struct riff_header) / sizeof (uint16_t),
+};
-static struct codec_api *ci;
-static int enc_channels;
+static const struct riff_header riff_header =
+{
+ /* "RIFF" header */
+ { 'R', 'I', 'F', 'F' }, /* riff_id */
+ 0, /* riff_size (*) */
+ /* format header */
+ { 'W', 'A', 'V', 'E' }, /* format */
+ { 'f', 'm', 't', ' ' }, /* format_id */
+ H_TO_LE32(16), /* format_size */
+ /* format data */
+ H_TO_LE16(1), /* audio_format */
+ 0, /* num_channels (*) */
+ 0, /* sample_rate (*) */
+ 0, /* byte_rate (*) */
+ 0, /* block_align (*) */
+ H_TO_LE16(PCM_DEPTH_BITS), /* bits_per_sample */
+ /* data header */
+ { 'd', 'a', 't', 'a' }, /* data_id */
+ 0 /* data_size (*) */
+ /* (*) updated during ENC_END_FILE event */
+};
+
+static void chunk_to_int32(int32_t *src) ICODE_ATTR;
+static void chunk_to_int32(int32_t *src)
+{
+ int32_t *dst = (int32_t *)input_buffer + PCM_SAMP_PER_CHUNK;
+ int32_t *src_end = dst + PCM_SAMP_PER_CHUNK;
-#define CHUNK_SIZE 20000
+ /* copy to IRAM before converting data */
+ memcpy(dst, src, PCM_CHUNK_SIZE);
-static long input_buffer[CHUNK_SIZE/2] IBSS_ATTR;
+ src = dst;
+ dst = (int32_t *)input_buffer;
-/* update file header info callback function */
-void enc_set_header(void *head_buffer, /* ptr to the file header data */
- int head_size, /* size of this header data */
- int num_pcm_sampl, /* amount of processed pcm samples */
- bool is_file_header) /* update file/chunk header */
-{
- if(is_file_header)
+ if (config.num_channels == 1)
{
- /* update file header before file closing */
- if(sizeof(WavpackHeader) + sizeof(wav_header_mono) < (unsigned)head_size)
+ /*
+ * |llllllllllllllll|rrrrrrrrrrrrrrrr| =>
+ * |mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm|
+ */
+ inline void to_int32(int32_t **src, int32_t **dst)
{
- char* riff_header = (char*)head_buffer + sizeof(WavpackHeader);
- char* wv_header = (char*)head_buffer + sizeof(wav_header_mono);
- int num_file_bytes = num_pcm_sampl * 2 * enc_channels;
- unsigned long ckSize;
-
- /* RIFF header and WVPK header have to be swapped */
- /* copy wavpack header to file start position */
- ci->memcpy(head_buffer, wv_header, sizeof(WavpackHeader));
- wv_header = head_buffer; /* recalc wavpack header position */
-
- if(enc_channels == 2)
- ci->memcpy(riff_header, wav_header_ster, sizeof(wav_header_ster));
- else
- ci->memcpy(riff_header, wav_header_mono, sizeof(wav_header_mono));
-
- /* update the Wavpack header first chunk size & total frame count */
- ckSize = htole32(((WavpackHeader*)wv_header)->ckSize)
- + sizeof(wav_header_mono);
- ((WavpackHeader*)wv_header)->total_samples = htole32(num_pcm_sampl);
- ((WavpackHeader*)wv_header)->ckSize = htole32(ckSize);
-
- /* update the RIFF WAV header size entries */
- *(long*)(riff_header+ 6) = htole32(num_file_bytes + 36);
- *(long*)(riff_header+42) = htole32(num_file_bytes);
+ int32_t t = *(*src)++;
+ /* endianness irrelevant */
+ *(*dst)++ = ((int16_t)t + (t >> 16)) >> 1;
+ } /* to_int32 */
+
+ do
+ {
+ /* read 10 longs and write 10 longs */
+ to_int32(&src, &dst);
+ to_int32(&src, &dst);
+ to_int32(&src, &dst);
+ to_int32(&src, &dst);
+ to_int32(&src, &dst);
+ to_int32(&src, &dst);
+ to_int32(&src, &dst);
+ to_int32(&src, &dst);
+ to_int32(&src, &dst);
+ to_int32(&src, &dst);
}
+ while(src < src_end);
+
+ return;
}
else
{
- /* update timestamp (block_index) */
- ((WavpackHeader*)head_buffer)->block_index = htole32(num_pcm_sampl);
+ /*
+ * |llllllllllllllll|rrrrrrrrrrrrrrrr| =>
+ * |llllllllllllllllllllllllllllllll|rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
+ */
+ inline void to_int32(int32_t **src, int32_t **dst)
+ {
+ int32_t t = *(*src)++;
+#ifdef ROCKBOX_BIG_ENDIAN
+ *(*dst)++ = t >> 16, *(*dst)++ = (int16_t)t;
+#else
+ *(*dst)++ = (int16_t)t, *(*dst)++ = t >> 16;
+#endif
+ } /* to_int32 */
+
+ do
+ {
+ /* read 10 longs and write 20 longs */
+ to_int32(&src, &dst);
+ to_int32(&src, &dst);
+ to_int32(&src, &dst);
+ to_int32(&src, &dst);
+ to_int32(&src, &dst);
+ to_int32(&src, &dst);
+ to_int32(&src, &dst);
+ to_int32(&src, &dst);
+ to_int32(&src, &dst);
+ to_int32(&src, &dst);
+ }
+ while (src < src_end);
+
+ return;
}
-}
+} /* chunk_to_int32 */
+/* called very often - inline */
+static inline bool is_file_data_ok(struct enc_file_event_data *data) ICODE_ATTR;
+static inline bool is_file_data_ok(struct enc_file_event_data *data)
+{
+ return data->rec_file >= 0 && (long)data->chunk->flags >= 0;
+} /* is_file_data_ok */
-enum codec_status codec_start(struct codec_api* api)
+/* called very often - inline */
+static inline bool on_write_chunk(struct enc_file_event_data *data) ICODE_ATTR;
+static inline bool on_write_chunk(struct enc_file_event_data *data)
+{
+ if (!is_file_data_ok(data))
+ return false;
+
+ if (data->chunk->enc_data == NULL)
+ {
+#ifdef ROCKBOX_HAS_LOGF
+ ci->logf("wvpk enc: NULL data");
+#endif
+ return true;
+ }
+
+ /* update timestamp (block_index) */
+ ((WavpackHeader *)data->chunk->enc_data)->block_index =
+ htole32(data->num_pcm_samples);
+
+ if (ci->write(data->rec_file, data->chunk->enc_data,
+ data->chunk->enc_size) != (ssize_t)data->chunk->enc_size)
+ return false;
+
+ data->num_pcm_samples += data->chunk->num_pcm;
+ return true;
+} /* on_write_chunk */
+
+static bool on_start_file(struct enc_file_event_data *data)
+{
+ if ((data->chunk->flags & CHUNKF_ERROR) || *data->filename == '\0')
+ return false;
+
+ data->rec_file = ci->open(data->filename, O_RDWR|O_CREAT|O_TRUNC);
+
+ if (data->rec_file < 0)
+ return false;
+
+ /* reset sample count */
+ data->num_pcm_samples = 0;
+
+ /* write template headers */
+ if (ci->write(data->rec_file, &wvpk_mdh, sizeof (wvpk_mdh))
+ != sizeof (wvpk_mdh) ||
+ ci->write(data->rec_file, &riff_header, sizeof (riff_header))
+ != sizeof (riff_header))
+ {
+ return false;
+ }
+
+ data->new_enc_size += sizeof(wvpk_mdh) + sizeof(riff_header);
+ return true;
+} /* on_start_file */
+
+static bool on_end_file(struct enc_file_event_data *data)
+{
+ struct
+ {
+ WavpackMetadataHeader wpmdh;
+ struct riff_header rhdr;
+ WavpackHeader wph;
+ } __attribute__ ((packed)) h;
+
+ uint32_t data_size;
+
+ if (!is_file_data_ok(data))
+ return false;
+
+ /* read template headers at start */
+ if (ci->lseek(data->rec_file, 0, SEEK_SET) != 0 ||
+ ci->read(data->rec_file, &h, sizeof (h)) != sizeof (h))
+ return false;
+
+ data_size = data->num_pcm_samples*config.num_channels*PCM_DEPTH_BYTES;
+
+ /** "RIFF" header **/
+ h.rhdr.riff_size = htole32(RIFF_FMT_HEADER_SIZE +
+ RIFF_FMT_DATA_SIZE + RIFF_DATA_HEADER_SIZE + data_size);
+
+ /* format data */
+ h.rhdr.num_channels = htole16(config.num_channels);
+ h.rhdr.sample_rate = htole32(config.sample_rate);
+ h.rhdr.byte_rate = htole32(config.sample_rate*config.num_channels*
+ PCM_DEPTH_BYTES);
+ h.rhdr.block_align = htole16(config.num_channels*PCM_DEPTH_BYTES);
+
+ /* data header */
+ h.rhdr.data_size = htole32(data_size);
+
+ /** Wavpack header **/
+ h.wph.ckSize = htole32(letoh32(h.wph.ckSize) + sizeof (h.wpmdh)
+ + sizeof (h.rhdr));
+ h.wph.total_samples = htole32(data->num_pcm_samples);
+
+ /* MDH|RIFF|WVPK => WVPK|MDH|RIFF */
+ if (ci->lseek(data->rec_file, 0, SEEK_SET)
+ != 0 ||
+ ci->write(data->rec_file, &h.wph, sizeof (h.wph))
+ != sizeof (h.wph) ||
+ ci->write(data->rec_file, &h.wpmdh, sizeof (h.wpmdh))
+ != sizeof (h.wpmdh) ||
+ ci->write(data->rec_file, &h.rhdr, sizeof (h.rhdr))
+ != sizeof (h.rhdr))
+ {
+ return false;
+ }
+
+ ci->fsync(data->rec_file);
+ ci->close(data->rec_file);
+ data->rec_file = -1;
+
+ return true;
+} /* on_end_file */
+
+static void enc_events_callback(enum enc_events event, void *data) ICODE_ATTR;
+static void enc_events_callback(enum enc_events event, void *data)
{
- int i;
- long t;
- uint32 *src;
- uint32 *dst;
- int chunk_size, num_chunks, samp_per_chunk;
- int enc_buffer_size;
- int enc_quality;
- WavpackConfig config;
- WavpackContext *wpc;
- bool cpu_boosted = true; /* start boosted */
-
- ci = api; // copy to global api pointer
+ if (event == ENC_WRITE_CHUNK)
+ {
+ if (on_write_chunk((struct enc_file_event_data *)data))
+ return;
+ }
+ else if (event == ENC_START_FILE)
+ {
+ /* write metadata header and RIFF header */
+ if (on_start_file((struct enc_file_event_data *)data))
+ return;
+ }
+ else if (event == ENC_END_FILE)
+ {
+ if (on_end_file((struct enc_file_event_data *)data))
+ return;
+ }
+ else
+ {
+ return;
+ }
+
+ ((struct enc_file_event_data *)data)->chunk->flags |= CHUNKF_ERROR;
+} /* enc_events_callback */
+
+static bool init_encoder(void)
+{
+ struct enc_inputs inputs;
+ struct enc_parameters params;
codec_init(ci);
- if(ci->enc_get_inputs == NULL ||
- ci->enc_set_parameters == NULL ||
- ci->enc_alloc_chunk == NULL ||
- ci->enc_free_chunk == NULL ||
- ci->enc_wavbuf_near_empty == NULL ||
- ci->enc_get_wav_data == NULL ||
- ci->enc_set_header_callback == NULL )
- return CODEC_ERROR;
+ if (ci->enc_get_inputs == NULL ||
+ ci->enc_set_parameters == NULL ||
+ ci->enc_get_chunk == NULL ||
+ ci->enc_finish_chunk == NULL ||
+ ci->enc_pcm_buf_near_empty == NULL ||
+ ci->enc_get_pcm_data == NULL ||
+ ci->enc_unget_pcm_data == NULL )
+ return false;
- ci->cpu_boost(true);
+ ci->enc_get_inputs(&inputs);
+
+ if (inputs.config->afmt != AFMT_WAVPACK)
+ return false;
- *ci->enc_set_header_callback = enc_set_header;
- ci->enc_get_inputs(&enc_buffer_size, &enc_channels, &enc_quality);
+ memset(&config, 0, sizeof (config));
+ config.bits_per_sample = PCM_DEPTH_BITS;
+ config.bytes_per_sample = PCM_DEPTH_BYTES;
+ config.sample_rate = inputs.sample_rate;
+ config.num_channels = inputs.num_channels;
+
+ wpc = WavpackOpenFileOutput ();
+
+ if (!WavpackSetConfiguration(wpc, &config, -1))
+ return false;
/* configure the buffer system */
- chunk_size = sizeof(long) + CHUNK_SIZE * enc_channels / 2;
- num_chunks = enc_buffer_size / chunk_size;
- samp_per_chunk = CHUNK_SIZE / 4;
+ params.afmt = AFMT_WAVPACK;
+ input_size = PCM_CHUNK_SIZE*inputs.num_channels / 2;
+ data_size = 105*input_size / 100;
+ input_size *= 2;
+ input_step = input_size / 4;
+ params.chunk_size = data_size;
+ params.enc_sample_rate = inputs.sample_rate;
+ params.reserve_bytes = 0;
+ params.events_callback = enc_events_callback;
- /* inform the main program about buffer dimensions and other params */
- /* add wav_header_mono as place holder to file start position */
- /* wav header and wvpk header have to be reordered later */
- ci->enc_set_parameters(chunk_size, num_chunks, samp_per_chunk,
- wav_header_mono, sizeof(wav_header_mono),
- AFMT_WAVPACK);
+ ci->enc_set_parameters(&params);
- wpc = WavpackOpenFileOutput ();
+ return true;
+} /* init_encoder */
+
+enum codec_status codec_start(struct codec_api* api)
+{
+ bool cpu_boosted;
+
+ ci = api; /* copy to global api pointer */
- memset (&config, 0, sizeof (config));
- config.bits_per_sample = 16;
- config.bytes_per_sample = 2;
- config.sample_rate = 44100;
- config.num_channels = enc_channels;
+#ifdef USE_IRAM
+ ci->memcpy(iramstart, iramcopy, iramend - iramstart);
+ ci->memset(iedata, 0, iend - iedata);
+#endif
- if (!WavpackSetConfiguration (wpc, &config, 1))
+ /* initialize params and config */
+ if (!init_encoder())
+ {
+ ci->enc_codec_loaded = -1;
return CODEC_ERROR;
+ }
/* main application waits for this flag during encoder loading */
- ci->enc_codec_loaded = true;
+ ci->enc_codec_loaded = 1;
+
+ ci->cpu_boost(true);
+ cpu_boosted = true;
/* main encoding loop */
while(!ci->stop_codec)
{
- while((src = (uint32*)ci->enc_get_wav_data(CHUNK_SIZE)) != NULL)
+ uint8_t *src;
+
+ while ((src = ci->enc_get_pcm_data(PCM_CHUNK_SIZE)) != NULL)
{
+ struct enc_chunk_hdr *chunk;
+ bool abort_chunk;
+ uint8_t *dst;
+ uint8_t *src_end;
+
if(ci->stop_codec)
break;
- if(ci->enc_wavbuf_near_empty() == 0)
+ abort_chunk = true;
+
+ if (!cpu_boosted && ci->enc_pcm_buf_near_empty() == 0)
{
- if(!cpu_boosted)
- {
- ci->cpu_boost(true);
- cpu_boosted = true;
- }
+ ci->cpu_boost(true);
+ cpu_boosted = true;
}
- dst = (uint32*)ci->enc_alloc_chunk() + 1;
+ chunk = ci->enc_get_chunk();
- WavpackStartBlock (wpc, (uint8*)dst, (uint8*)dst + CHUNK_SIZE);
+ /* reset counts and pointer */
+ chunk->enc_size = 0;
+ chunk->num_pcm = 0;
+ chunk->enc_data = NULL;
- if(enc_channels == 2)
- {
- for (i=0; i<CHUNK_SIZE/4; i++)
- {
- t = (long)*src++;
+ dst = ENC_CHUNK_SKIP_HDR(dst, chunk);
- input_buffer[2*i + 0] = t >> 16;
- input_buffer[2*i + 1] = (short)t;
- }
- }
- else
+ WavpackStartBlock(wpc, dst, dst + data_size);
+
+ chunk_to_int32((uint32_t*)src);
+ src = input_buffer;
+ src_end = src + input_size;
+
+ /* encode chunk in four steps yielding between each */
+ do
{
- for (i=0; i<CHUNK_SIZE/4; i++)
+ if (WavpackPackSamples(wpc, (int32_t *)src,
+ PCM_SAMP_PER_CHUNK/4))
{
- t = (long)*src++;
- t = (((t<<16)>>16) + (t>>16)) >> 1; /* left+right */
-
- input_buffer[i] = t;
+ chunk->num_pcm += PCM_SAMP_PER_CHUNK/4;
+ ci->yield();
+ /* could've been stopped in some way */
+ abort_chunk = ci->stop_codec ||
+ (chunk->flags & CHUNKF_ABORT);
}
- }
- if (!WavpackPackSamples (wpc, input_buffer, CHUNK_SIZE/4))
- return CODEC_ERROR;
+ src += input_step;
+ }
+ while (!abort_chunk && src < src_end);
+ if (!abort_chunk)
+ {
+ chunk->enc_data = dst;
+ if (chunk->num_pcm < PCM_SAMP_PER_CHUNK)
+ ci->enc_unget_pcm_data(PCM_CHUNK_SIZE - chunk->num_pcm*4);
/* finish the chunk and store chunk size info */
- dst[-1] = WavpackFinishBlock (wpc);
-
- ci->enc_free_chunk();
- ci->yield();
+ chunk->enc_size = WavpackFinishBlock(wpc);
+ ci->enc_finish_chunk();
+ }
}
- if(ci->enc_wavbuf_near_empty())
+ if (cpu_boosted && ci->enc_pcm_buf_near_empty() != 0)
{
- if(cpu_boosted)
- {
- ci->cpu_boost(false);
- cpu_boosted = false;
- }
+ ci->cpu_boost(false);
+ cpu_boosted = false;
}
+
ci->yield();
}
- if(cpu_boosted) /* set initial boost state */
+ if (cpu_boosted) /* set initial boost state */
ci->cpu_boost(false);
/* reset parameters to initial state */
- ci->enc_set_parameters(0, 0, 0, 0, 0, 0);
+ ci->enc_set_parameters(NULL);
/* main application waits for this flag during encoder removing */
- ci->enc_codec_loaded = false;
+ ci->enc_codec_loaded = 0;
return CODEC_OK;
-}
-#endif
+} /* codec_start */
+
+#endif /* ndef SIMULATOR */