1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2009 Yoshihisa Uchida
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.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include "pcm_common.h"
23 #include "support_formats.h"
29 static struct pcm_format
*fmt
;
31 static bool set_format(struct pcm_format
*format
)
35 if (fmt
->bitspersample
!= 32 && fmt
->bitspersample
!= 64)
37 DEBUGF("CODEC_ERROR: ieee float must be 32 or 64 bitspersample: %d\n",
42 fmt
->bytespersample
= fmt
->bitspersample
>> 3;
43 fmt
->samplesperblock
= fmt
->blockalign
/ (fmt
->bytespersample
* fmt
->channels
);
45 /* chunksize = about 1/50[sec] data */
46 fmt
->chunksize
= (ci
->id3
->frequency
/ (50 * fmt
->samplesperblock
))
52 static struct pcm_pos
*get_seek_pos(long seek_time
,
53 uint8_t *(*read_buffer
)(size_t *realsize
))
55 static struct pcm_pos newpos
;
56 uint32_t newblock
= ((uint64_t)seek_time
* ci
->id3
->frequency
)
57 / (1000LL * fmt
->samplesperblock
);
60 newpos
.pos
= newblock
* fmt
->blockalign
;
61 newpos
.samples
= newblock
* fmt
->samplesperblock
;
65 static int decode(const uint8_t *inbuf
, size_t inbufsize
,
66 int32_t *outbuf
, int *outbufsize
)
73 if (fmt
->bitspersample
== 32)
75 for (i
= 0; i
< inbufsize
; i
+= 4)
77 if (fmt
->is_little_endian
)
79 pcm
= (inbuf
[0]<<5)|(inbuf
[1]<<13)|((inbuf
[2]|0x80)<<21);
80 exp
= ((inbuf
[2]>>7)|((inbuf
[3]&0x7f)<<1)) - 127;
81 sgn
= inbuf
[3] & 0x80;
85 pcm
= (inbuf
[3]<<5)|(inbuf
[2]<<13)|((inbuf
[1]|0x80)<<21);
86 exp
= ((inbuf
[1]>>7)|((inbuf
[0]&0x7f)<<1)) - 127;
87 sgn
= inbuf
[0] & 0x80;
89 if (exp
> -29 && exp
< 0)
98 pcm
= (sgn
)?-(1<<28):(1<<28)-1;
103 *outbufsize
= inbufsize
>> 2;
107 for (i
= 0; i
< inbufsize
; i
+= 8)
109 if (fmt
->is_little_endian
)
111 pcm
= inbuf
[3]|(inbuf
[4]<<8)|(inbuf
[5]<<16)|(((inbuf
[6]&0x0f)|0x10)<<24);
112 exp
= (((inbuf
[6]&0xf0)>>4)|((inbuf
[7]&0x7f)<<4)) - 1023;
113 sgn
= inbuf
[7] & 0x80;
117 pcm
= inbuf
[4]|(inbuf
[3]<<8)|(inbuf
[2]<<16)|(((inbuf
[1]&0x0f)|0x10)<<24);
118 exp
= (((inbuf
[1]&0xf0)>>4)|((inbuf
[0]&0x7f)<<4)) - 1023;
119 sgn
= inbuf
[0] & 0x80;
121 if (exp
> -29 && exp
< 0)
130 pcm
= (sgn
)?-(1<<28):(1<<28)-1;
135 *outbufsize
= inbufsize
>> 3;
138 if (fmt
->channels
== 2)
144 static const struct pcm_codec codec
= {
150 const struct pcm_codec
*get_ieee_float_codec(void)