Mercurial > repos > blastem
annotate flac.c @ 2296:789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sun, 19 Feb 2023 21:12:46 -0800 |
parents | |
children | 9d68799f945b |
rev | line source |
---|---|
2296
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
1 #include <stdlib.h> |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
2 #include <string.h> |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
3 #include <inttypes.h> |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
4 #include "flac.h" |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
5 |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
6 static uint8_t read_byte_buffer(flac_file *f) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
7 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
8 if (f->offset >= f->buffer_size) { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
9 return 0; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
10 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
11 uint8_t *buf = f->read_data; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
12 return buf[f->offset++]; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
13 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
14 |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
15 static void seek_buffer(flac_file *f, uint32_t offset, uint8_t relative) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
16 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
17 f->offset = relative ? f->offset + offset : offset; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
18 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
19 |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
20 static uint8_t read_byte_file(flac_file *f) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
21 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
22 int result = fgetc(f->read_data); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
23 if (result == EOF) { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
24 return 0; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
25 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
26 return result; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
27 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
28 |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
29 static void seek_file(flac_file *f, uint32_t offset, uint8_t relative) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
30 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
31 fseek(f->read_data, offset, relative ? SEEK_CUR : SEEK_SET); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
32 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
33 |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
34 static void read_chars(flac_file *f, char *dest, uint32_t count) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
35 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
36 for (; count > 0; --count) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
37 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
38 *(dest++) = f->read_byte(f); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
39 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
40 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
41 |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
42 static uint16_t read16(flac_file *f) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
43 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
44 uint16_t ret = f->read_byte(f) << 8; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
45 ret |= f->read_byte(f); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
46 return ret; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
47 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
48 |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
49 static uint32_t read_bits(flac_file *f, uint32_t num_bits) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
50 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
51 uint32_t ret = 0; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
52 while (num_bits) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
53 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
54 if (!f->bits) { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
55 f->cur_byte = f->read_byte(f); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
56 f->bits = 8; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
57 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
58 uint32_t new_bits = f->bits; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
59 if (new_bits > num_bits) { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
60 new_bits = num_bits; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
61 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
62 ret <<= new_bits; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
63 uint32_t mask = (1 << new_bits) - 1; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
64 ret |= (f->cur_byte >> (f->bits - new_bits)) & mask; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
65 f->bits -= new_bits; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
66 num_bits -= new_bits; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
67 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
68 return ret; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
69 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
70 |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
71 static uint64_t read_bits64(flac_file *f, uint64_t num_bits) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
72 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
73 uint64_t ret = 0; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
74 while (num_bits) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
75 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
76 if (!f->bits) { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
77 f->cur_byte = f->read_byte(f); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
78 f->bits = 8; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
79 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
80 uint64_t new_bits = f->bits; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
81 if (new_bits > num_bits) { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
82 new_bits = num_bits; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
83 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
84 ret <<= new_bits; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
85 uint64_t mask = (1 << new_bits) - 1; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
86 ret |= f->cur_byte & mask; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
87 f->cur_byte >>= new_bits; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
88 f->bits -= new_bits; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
89 num_bits -= new_bits; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
90 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
91 return ret; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
92 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
93 |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
94 typedef struct { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
95 uint32_t size; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
96 uint8_t type; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
97 uint8_t is_last; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
98 } meta_block_header; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
99 |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
100 enum { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
101 STREAMINFO, |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
102 PADDING, |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
103 APPLICATION, |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
104 SEEKTABLE, |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
105 VORBIS_COMMENT, |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
106 CUESHEET, |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
107 PICTURE |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
108 }; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
109 |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
110 static void read_meta_block_header(flac_file *f, meta_block_header *dest) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
111 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
112 dest->is_last = read_bits(f, 1); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
113 dest->type = read_bits(f, 7); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
114 dest->size = read_bits(f, 24); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
115 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
116 |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
117 static void parse_streaminfo(flac_file *f) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
118 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
119 read16(f);//min block size |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
120 read16(f);//max block size |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
121 read_bits(f, 24);//min frame size |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
122 read_bits(f, 24);//max frame size |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
123 f->sample_rate = read_bits(f, 20); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
124 f->channels = read_bits(f, 3) + 1; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
125 f->bits_per_sample = read_bits(f, 5) + 1; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
126 f->total_samples = read_bits64(f, 36); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
127 f->seek(f, 16, 1);//MD5 |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
128 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
129 |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
130 static uint8_t parse_header(flac_file *f) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
131 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
132 char id[4]; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
133 read_chars(f, id, sizeof(id)); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
134 if (memcmp("fLaC", id, sizeof(id))) { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
135 return 0; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
136 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
137 meta_block_header header; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
138 do { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
139 read_meta_block_header(f, &header); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
140 if (header.type == STREAMINFO) { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
141 parse_streaminfo(f); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
142 } else { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
143 f->seek(f, header.size, 1); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
144 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
145 } while (!header.is_last); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
146 return 1; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
147 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
148 |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
149 flac_file *flac_file_from_buffer(void *buffer, uint32_t size) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
150 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
151 flac_file *f = calloc(1, sizeof(flac_file)); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
152 f->read_data = buffer; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
153 f->read_byte = read_byte_buffer; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
154 f->seek = seek_buffer; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
155 f->buffer_size = size; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
156 if (parse_header(f)) { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
157 return f; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
158 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
159 free(f); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
160 return NULL; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
161 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
162 |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
163 flac_file *flac_file_from_file(FILE *file) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
164 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
165 flac_file *f = calloc(1, sizeof(flac_file)); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
166 f->read_data = file; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
167 f->read_byte = read_byte_file; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
168 f->seek = seek_file; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
169 if (parse_header(f)) { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
170 return f; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
171 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
172 free(f); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
173 return NULL; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
174 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
175 |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
176 static uint64_t read_utf64(flac_file *f) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
177 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
178 uint8_t byte = f->read_byte(f); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
179 if (!(byte & 0x80)) { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
180 return byte; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
181 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
182 uint8_t mask = 0x40; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
183 uint8_t length = 0; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
184 while (byte & mask) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
185 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
186 mask >>= 1; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
187 length++; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
188 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
189 uint64_t value = byte + (mask - 1); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
190 for (uint8_t i = 0; i < length; i++) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
191 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
192 value <<= 6; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
193 value |= f->read_byte(f) & 0x3F; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
194 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
195 return value; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
196 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
197 |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
198 static uint32_t read_utf32(flac_file *f) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
199 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
200 uint8_t byte = f->read_byte(f); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
201 if (!(byte & 0x80)) { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
202 return byte; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
203 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
204 uint8_t mask = 0x40; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
205 uint8_t length = 0; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
206 while (byte & mask) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
207 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
208 mask >>= 1; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
209 length++; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
210 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
211 uint32_t value = byte + (mask - 1); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
212 for (uint8_t i = 0; i < length; i++) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
213 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
214 value <<= 6; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
215 value |= f->read_byte(f) & 0x3F; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
216 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
217 return value; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
218 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
219 |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
220 static uint8_t parse_frame_header(flac_file *f) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
221 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
222 uint16_t sync = read_bits(f, 14); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
223 if (sync != 0x3FFE) { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
224 fprintf(stderr, "Invalid sync FLAC sync pattern: %X\n", sync); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
225 return 0; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
226 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
227 read_bits(f, 1);//reserved |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
228 uint8_t block_size_strategy = read_bits(f, 1); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
229 uint8_t block_size_code = read_bits(f, 4); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
230 uint8_t sample_rate_code = read_bits(f, 4); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
231 uint8_t channels = read_bits(f, 4); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
232 uint8_t joint_stereo = 0; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
233 if (channels > 7) { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
234 joint_stereo = (channels & 7) + 1; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
235 channels = 2; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
236 } else { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
237 ++channels; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
238 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
239 f->frame_channels = channels; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
240 f->frame_joint_stereo = joint_stereo; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
241 uint8_t bits_per_sample_code = read_bits(f, 3); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
242 if (!bits_per_sample_code) { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
243 f->frame_bits_per_sample = f->bits_per_sample; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
244 } else if (bits_per_sample_code < 3) { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
245 f->frame_bits_per_sample = 4 + 4 * bits_per_sample_code; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
246 } else { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
247 f->frame_bits_per_sample = 4 * bits_per_sample_code; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
248 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
249 read_bits(f, 1);//reserved |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
250 uint32_t block_num; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
251 if (block_size_strategy) { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
252 f->frame_start_sample = read_utf64(f); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
253 } else { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
254 block_num = read_utf32(f); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
255 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
256 uint32_t block_size = 0; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
257 switch (block_size_code) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
258 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
259 case 0: |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
260 fputs("Detected reserved block size 0", stderr); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
261 return 0; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
262 case 1: |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
263 block_size = 192; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
264 break; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
265 case 6: |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
266 block_size = f->read_byte(f) + 1; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
267 break; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
268 case 7: |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
269 block_size = read16(f) + 1; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
270 break; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
271 default: |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
272 if (block_size_code < 8) { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
273 block_size = 576 * (1 << (block_size_code - 2)); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
274 } else { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
275 block_size = 256 * (1 << (block_size_code - 8)); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
276 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
277 break; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
278 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
279 f->frame_block_size = block_size; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
280 if (!block_size_strategy) { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
281 f->frame_start_sample = ((uint64_t)block_num) * ((uint64_t)block_size); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
282 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
283 uint32_t sample_rate; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
284 switch (sample_rate_code) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
285 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
286 case 15: |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
287 fputs("Invalid frame header sample rate", stderr); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
288 case 0: |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
289 sample_rate = f->sample_rate; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
290 break; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
291 case 1: |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
292 sample_rate = 88200; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
293 break; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
294 case 2: |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
295 sample_rate = 176400; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
296 break; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
297 case 3: |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
298 sample_rate = 192000; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
299 break; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
300 case 4: |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
301 sample_rate = 8000; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
302 break; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
303 case 5: |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
304 sample_rate = 16000; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
305 break; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
306 case 6: |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
307 sample_rate = 22050; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
308 break; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
309 case 7: |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
310 sample_rate = 44100; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
311 break; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
312 case 8: |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
313 sample_rate = 32000; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
314 break; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
315 case 9: |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
316 sample_rate = 44100; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
317 break; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
318 case 10: |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
319 sample_rate = 48000; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
320 break; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
321 case 11: |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
322 sample_rate = 96000; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
323 break; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
324 case 12: |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
325 sample_rate = f->read_byte(f) * 1000; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
326 break; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
327 case 13: |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
328 sample_rate = read16(f); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
329 break; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
330 case 14: |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
331 sample_rate = read16(f) * 10; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
332 break; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
333 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
334 f->frame_sample_rate = sample_rate; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
335 f->read_byte(f);//CRC-8 |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
336 return 1; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
337 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
338 |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
339 enum { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
340 SUBFRAME_CONSTANT, |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
341 SUBFRAME_VERBATIM, |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
342 SUBFRAME_FIXED = 8, |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
343 SUBFRAME_LPC = 0x20, |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
344 }; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
345 |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
346 static int32_t sign_extend(uint32_t value, uint32_t bits) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
347 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
348 if (value & (1 << (bits - 1))) { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
349 value |= ~((1 << bits) - 1); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
350 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
351 return value; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
352 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
353 |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
354 static int32_t signed_sample(uint32_t sample_bits, uint32_t sample, uint8_t wasted_bits) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
355 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
356 sample <<= wasted_bits; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
357 sample = sign_extend(sample, sample_bits); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
358 return sample; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
359 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
360 |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
361 static void decode_residuals(flac_file *f, flac_subframe *sub, int64_t *coefficients, uint32_t order, int64_t shift) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
362 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
363 uint8_t residual_method = read_bits(f, 2); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
364 uint8_t rice_param_bits = residual_method ? 5 : 4; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
365 uint32_t partition_count = 1 << read_bits(f, 4); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
366 uint32_t cur = order; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
367 uint32_t partition_size = f->frame_block_size / partition_count; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
368 for (uint32_t partition = 0; partition < partition_count; partition++) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
369 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
370 uint32_t rice_param = read_bits(f, rice_param_bits); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
371 if (rice_param == (1 << rice_param_bits) - 1) { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
372 //escape code, residuals are unencoded |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
373 rice_param = read_bits(f, rice_param_bits); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
374 for (uint32_t end = partition ? cur + partition_size : partition_size; cur < end; cur++) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
375 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
376 int64_t prediction = 0; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
377 for (uint32_t i = 0; i < order; i++) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
378 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
379 prediction += ((int64_t)sub->decoded[cur - 1 - i]) * coefficients[i]; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
380 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
381 if (shift) { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
382 prediction >>= shift; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
383 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
384 prediction += sign_extend(read_bits(f, rice_param), rice_param); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
385 sub->decoded[cur] = prediction; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
386 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
387 } else { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
388 for (uint32_t end = partition ? cur + partition_size : partition_size; cur < end; cur++) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
389 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
390 int64_t prediction = 0; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
391 for (uint32_t i = 0; i < order; i++) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
392 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
393 prediction += ((int64_t)sub->decoded[cur - 1 - i]) * coefficients[i]; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
394 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
395 if (shift) { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
396 prediction >>= shift; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
397 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
398 uint32_t residual = 0; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
399 while (!read_bits(f, 1)) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
400 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
401 ++residual; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
402 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
403 residual <<= rice_param; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
404 residual |= read_bits(f, rice_param); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
405 if (residual & 1) { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
406 sub->decoded[cur] = prediction - (residual >> 1) - 1; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
407 } else { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
408 sub->decoded[cur] = prediction + (residual >> 1); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
409 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
410 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
411 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
412 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
413 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
414 |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
415 static void decode_subframe(flac_file *f, flac_subframe *sub) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
416 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
417 if (f->frame_block_size > sub->allocated_samples) { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
418 sub->decoded = realloc(sub->decoded, sizeof(int32_t) * f->frame_block_size); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
419 sub->allocated_samples = f->frame_block_size ; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
420 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
421 int64_t prediction_coefficients[32]; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
422 read_bits(f, 1);//reserved |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
423 uint8_t type = read_bits(f, 6); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
424 uint8_t has_wasted_bits = read_bits(f, 1); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
425 uint8_t wasted_bits = 0; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
426 if (has_wasted_bits) { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
427 ++wasted_bits; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
428 while (!read_bits(f, 1)) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
429 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
430 ++wasted_bits; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
431 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
432 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
433 uint32_t sample_bits = f->frame_bits_per_sample - wasted_bits; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
434 if (f->frame_joint_stereo) { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
435 int channel = sub - f->subframes; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
436 if (f->frame_joint_stereo == 2 && !channel || (channel && f->frame_joint_stereo != 2)) { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
437 sample_bits++; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
438 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
439 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
440 if (type == SUBFRAME_CONSTANT) { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
441 int32_t sample = signed_sample(sample_bits, read_bits(f, sample_bits), wasted_bits); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
442 for (uint32_t i = 0; i < f->frame_block_size; i++) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
443 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
444 sub->decoded[i] = sample; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
445 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
446 } else if (type == SUBFRAME_VERBATIM) { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
447 for (uint32_t i = 0; i < f->frame_block_size; i++) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
448 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
449 sub->decoded[i] = signed_sample(sample_bits, read_bits(f, sample_bits), wasted_bits); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
450 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
451 } else if (type & SUBFRAME_LPC) { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
452 uint32_t order = (type & 0x1F) + 1; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
453 for (uint32_t i = 0; i < order; i++) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
454 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
455 sub->decoded[i] = signed_sample(sample_bits, read_bits(f, sample_bits), wasted_bits); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
456 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
457 uint32_t coefficient_bits = read_bits(f, 4) + 1; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
458 int64_t shift_bits = read_bits(f, 5); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
459 for (uint32_t i = 0; i < order; i++) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
460 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
461 prediction_coefficients[i] = sign_extend(read_bits(f, coefficient_bits), coefficient_bits); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
462 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
463 decode_residuals(f, sub, prediction_coefficients, order, shift_bits); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
464 } else if (type & SUBFRAME_FIXED) { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
465 uint32_t order = type & 7; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
466 for (uint32_t i = 0; i < order; i++) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
467 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
468 sub->decoded[i] = signed_sample(sample_bits, read_bits(f, sample_bits), wasted_bits); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
469 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
470 switch (order) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
471 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
472 case 1: |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
473 prediction_coefficients[0] = 1; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
474 break; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
475 case 2: |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
476 prediction_coefficients[0] = 2; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
477 prediction_coefficients[1] = -1; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
478 break; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
479 case 3: |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
480 prediction_coefficients[0] = 3; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
481 prediction_coefficients[1] = -3; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
482 prediction_coefficients[2] = 1; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
483 break; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
484 case 4: |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
485 prediction_coefficients[0] = 4; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
486 prediction_coefficients[1] = -6; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
487 prediction_coefficients[2] = 4; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
488 prediction_coefficients[3] = -1; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
489 break; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
490 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
491 decode_residuals(f, sub, prediction_coefficients, order, 0); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
492 } else { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
493 fprintf(stderr, "Invalid subframe type %X\n", type); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
494 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
495 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
496 |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
497 static uint8_t decode_frame(flac_file *f) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
498 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
499 if (!parse_frame_header(f)) { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
500 return 0; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
501 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
502 if (f->frame_channels > f->subframe_alloc) { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
503 f->subframes = realloc(f->subframes, sizeof(flac_subframe) * f->frame_channels); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
504 memset(f->subframes + f->subframe_alloc, 0, sizeof(flac_subframe) * (f->frame_channels - f->subframe_alloc)); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
505 f->subframe_alloc = f->frame_channels; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
506 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
507 for (uint8_t channel = 0; channel < f->frame_channels; channel++) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
508 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
509 decode_subframe(f, f->subframes + channel); |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
510 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
511 f->bits = 0; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
512 read16(f);//Frame footer CRC-16 |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
513 f->frame_sample_pos = 0; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
514 return 1; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
515 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
516 |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
517 uint8_t flac_get_sample(flac_file *f, int16_t *out, uint8_t desired_channels) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
518 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
519 if (f->frame_sample_pos == f->frame_block_size) { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
520 if (!decode_frame(f)) { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
521 return 0; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
522 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
523 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
524 uint8_t copy_channels; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
525 if (f->frame_channels == 1 && desired_channels > 1) { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
526 int16_t sample = f->subframes->decoded[f->frame_sample_pos]; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
527 *(out++) = sample; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
528 *(out++) = sample; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
529 copy_channels = 2; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
530 } else { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
531 int32_t left, right, mid, diff; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
532 switch (f->frame_joint_stereo) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
533 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
534 case 0: |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
535 copy_channels = desired_channels; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
536 if (copy_channels > f->frame_channels) { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
537 copy_channels = f->frame_channels; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
538 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
539 for (uint8_t i = 0; i < copy_channels; i++) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
540 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
541 *(out++) = f->subframes[i].decoded[f->frame_sample_pos]; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
542 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
543 break; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
544 case 1: |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
545 //left-side |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
546 copy_channels = 2; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
547 *(out++) = left = f->subframes[0].decoded[f->frame_sample_pos]; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
548 if (desired_channels > 1) { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
549 *(out++) = left + f->subframes[1].decoded[f->frame_sample_pos]; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
550 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
551 break; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
552 case 2: |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
553 //side-right |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
554 copy_channels = 2; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
555 right = f->subframes[1].decoded[f->frame_sample_pos]; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
556 left = right + f->subframes[0].decoded[f->frame_sample_pos]; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
557 *(out++) = left; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
558 if (desired_channels > 1) { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
559 *(out++) = right; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
560 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
561 break; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
562 case 3: |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
563 //mid-side |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
564 copy_channels = 2; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
565 mid = f->subframes[0].decoded[f->frame_sample_pos]; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
566 diff = f->subframes[1].decoded[f->frame_sample_pos]; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
567 left = (diff + 2 * mid) >> 1; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
568 *(out++) = left; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
569 if (desired_channels > 1) { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
570 *(out++) = left - diff; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
571 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
572 break; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
573 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
574 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
575 for (uint8_t i = copy_channels; i < desired_channels; i++) |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
576 { |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
577 *(out++) = 0; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
578 } |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
579 f->frame_sample_pos++; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
580 |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
581 return 1; |
789802d99629
Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
582 } |