annotate flac.c @ 2496:187bc857a76a default tip

Fix bug in MED mapper protection bit implementation
author Michael Pavone <pavone@retrodev.com>
date Sun, 28 Apr 2024 23:33:11 -0700
parents 9d68799f945b
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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
2298
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
20 static uint32_t tell_buffer(flac_file *f)
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
21 {
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
22 return f->offset;
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
23 }
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
24
2296
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
25 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
26 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
27 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
28 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
29 return 0;
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 return result;
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 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
35 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
36 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
37 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
38
2298
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
39 static uint32_t tell_file(flac_file *f)
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
40 {
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
41 return ftell(f->read_data);
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
42 }
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
43
2296
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
44 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
45 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
46 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
47 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
48 *(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
49 }
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
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
52 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
53 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
54 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
55 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
56 return ret;
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
2298
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
59 static uint64_t read64(flac_file *f)
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
60 {
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
61 uint64_t value = ((uint64_t)f->read_byte(f)) << 56;
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
62 value |= ((uint64_t)f->read_byte(f)) << 48;
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
63 value |= ((uint64_t)f->read_byte(f)) << 40;
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
64 value |= ((uint64_t)f->read_byte(f)) << 32;
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
65 value |= ((uint64_t)f->read_byte(f)) << 24;
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
66 value |= f->read_byte(f) << 16;
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
67 value |= f->read_byte(f) << 8;
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
68 value |= f->read_byte(f);
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
69 return value;
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
70 }
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
71
2296
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
72 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
73 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
74 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
75 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
76 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
77 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
78 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
79 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
80 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
81 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
82 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
83 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
84 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
85 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
86 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
87 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
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 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
95 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
96 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
97 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
98 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
99 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
100 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
101 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
102 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
103 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
104 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
105 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
106 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
107 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
108 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
109 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
110 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
111 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
112 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
113 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
114 return ret;
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 typedef struct {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
118 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
119 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
120 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
121 } 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
122
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
123 enum {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
124 STREAMINFO,
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
125 PADDING,
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
126 APPLICATION,
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
127 SEEKTABLE,
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
128 VORBIS_COMMENT,
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
129 CUESHEET,
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
130 PICTURE
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
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
133 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
134 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
135 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
136 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
137 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
138 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
139
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
140 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
141 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
142 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
143 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
144 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
145 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
146 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
147 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
148 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
149 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
150 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
151 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
152
2298
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
153 static void parse_seektable(flac_file *f, uint32_t size)
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
154 {
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
155 f->num_seekpoints = size / 18;
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
156 f->seekpoints = calloc(f->num_seekpoints, sizeof(flac_seekpoint));
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
157 for (uint32_t i = 0; i < f->num_seekpoints; i++)
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
158 {
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
159 f->seekpoints[i].sample_number = read64(f);
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
160 f->seekpoints[i].offset = read64(f);
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
161 f->seekpoints[i].sample_count = read16(f);
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
162 }
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
163 }
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
164
2296
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
165 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
166 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
167 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
168 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
169 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
170 return 0;
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 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
173 do {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
174 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
175 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
176 parse_streaminfo(f);
2298
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
177 } else if (header.type == SEEKTABLE) {
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
178 parse_seektable(f, header.size);
2296
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
179 } else {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
180 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
181 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
182 } while (!header.is_last);
2298
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
183 f->first_frame_offset = f->tell(f);
2296
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
184 return 1;
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
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
187 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
188 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
189 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
190 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
191 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
192 f->seek = seek_buffer;
2298
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
193 f->tell = tell_buffer;
2296
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
194 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
195 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
196 return f;
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 free(f);
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
199 return NULL;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
200 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
201
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
202 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
203 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
204 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
205 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
206 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
207 f->seek = seek_file;
2298
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
208 f->tell = tell_file;
2296
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
209 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
210 return f;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
211 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
212 free(f);
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
213 return NULL;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
214 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
215
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
216 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
217 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
218 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
219 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
220 return byte;
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 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
223 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
224 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
225 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
226 mask >>= 1;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
227 length++;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
228 }
2298
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
229 uint64_t value = byte & (mask - 1);
2296
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
230 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
231 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
232 value <<= 6;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
233 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
234 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
235 return value;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
236 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
237
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
238 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
239 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
240 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
241 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
242 return byte;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
243 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
244 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
245 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
246 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
247 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
248 mask >>= 1;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
249 length++;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
250 }
2298
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
251 uint32_t value = byte & (mask - 1);
2296
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
252 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
253 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
254 value <<= 6;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
255 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
256 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
257 return value;
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
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
260 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
261 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
262 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
263 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
264 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
265 return 0;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
266 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
267 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
268 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
269 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
270 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
271 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
272 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
273 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
274 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
275 channels = 2;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
276 } else {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
277 ++channels;
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_channels = channels;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
280 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
281 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
282 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
283 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
284 } 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
285 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
286 } else {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
287 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
288 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
289 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
290 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
291 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
292 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
293 } else {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
294 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
295 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
296 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
297 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
298 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
299 case 0:
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
300 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
301 return 0;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
302 case 1:
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
303 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
304 break;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
305 case 6:
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
306 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
307 break;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
308 case 7:
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
309 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
310 break;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
311 default:
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
312 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
313 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
314 } else {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
315 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
316 }
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 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
319 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
320 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
321 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
322 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
323 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
324 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
325 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
326 case 15:
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
327 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
328 case 0:
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
329 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
330 break;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
331 case 1:
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
332 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
333 break;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
334 case 2:
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
335 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
336 break;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
337 case 3:
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
338 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
339 break;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
340 case 4:
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
341 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
342 break;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
343 case 5:
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
344 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
345 break;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
346 case 6:
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
347 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
348 break;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
349 case 7:
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
350 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
351 break;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
352 case 8:
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
353 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
354 break;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
355 case 9:
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
356 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
357 break;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
358 case 10:
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
359 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
360 break;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
361 case 11:
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
362 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
363 break;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
364 case 12:
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
365 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
366 break;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
367 case 13:
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
368 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
369 break;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
370 case 14:
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
371 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
372 break;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
373 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
374 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
375 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
376 return 1;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
377 }
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 enum {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
380 SUBFRAME_CONSTANT,
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
381 SUBFRAME_VERBATIM,
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
382 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
383 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
384 };
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
385
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
386 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
387 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
388 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
389 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
390 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
391 return value;
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
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
394 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
395 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
396 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
397 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
398 return sample;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
399 }
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 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
402 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
403 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
404 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
405 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
406 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
407 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
408 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
409 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
410 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
411 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
412 //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
413 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
414 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
415 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
416 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
417 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
418 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
419 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
420 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
421 if (shift) {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
422 prediction >>= shift;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
423 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
424 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
425 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
426 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
427 } else {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
428 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
429 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
430 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
431 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
432 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
433 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
434 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
435 if (shift) {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
436 prediction >>= shift;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
437 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
438 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
439 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
440 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
441 ++residual;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
442 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
443 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
444 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
445 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
446 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
447 } else {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
448 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
449 }
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 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
452 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
453 }
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 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
456 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
457 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
458 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
459 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
460 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
461 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
462 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
463 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
464 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
465 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
466 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
467 ++wasted_bits;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
468 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
469 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
470 ++wasted_bits;
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 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
473 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
474 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
475 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
476 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
477 sample_bits++;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
478 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
479 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
480 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
481 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
482 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
483 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
484 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
485 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
486 } 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
487 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
488 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
489 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
490 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
491 } 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
492 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
493 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
494 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
495 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
496 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
497 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
498 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
499 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
500 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
501 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
502 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
503 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
504 } 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
505 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
506 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
507 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
508 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
509 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
510 switch (order)
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
511 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
512 case 1:
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
513 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
514 break;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
515 case 2:
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
516 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
517 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
518 break;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
519 case 3:
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
520 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
521 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
522 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
523 break;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
524 case 4:
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
525 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
526 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
527 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
528 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
529 break;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
530 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
531 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
532 } else {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
533 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
534 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
535 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
536
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
537 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
538 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
539 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
540 return 0;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
541 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
542 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
543 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
544 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
545 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
546 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
547 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
548 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
549 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
550 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
551 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
552 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
553 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
554 return 1;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
555 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
556
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
557 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
558 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
559 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
560 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
561 return 0;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
562 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
563 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
564 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
565 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
566 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
567 *(out++) = sample;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
568 *(out++) = sample;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
569 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
570 } else {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
571 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
572 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
573 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
574 case 0:
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
575 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
576 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
577 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
578 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
579 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
580 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
581 *(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
582 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
583 break;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
584 case 1:
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
585 //left-side
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
586 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
587 *(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
588 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
589 *(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
590 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
591 break;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
592 case 2:
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
593 //side-right
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
594 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
595 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
596 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
597 *(out++) = left;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
598 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
599 *(out++) = right;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
600 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
601 break;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
602 case 3:
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
603 //mid-side
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
604 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
605 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
606 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
607 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
608 *(out++) = left;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
609 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
610 *(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
611 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
612 break;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
613 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
614 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
615 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
616 {
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
617 *(out++) = 0;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
618 }
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
619 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
620
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
621 return 1;
789802d99629 Add basic FLAC decoder and add FLAC playback support to the media player
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
622 }
2298
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
623
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
624 void flac_seek(flac_file *f, uint64_t sample_number)
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
625 {
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
626 if (sample_number >= f->frame_start_sample && sample_number < f->frame_start_sample + f->frame_block_size) {
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
627 f->frame_sample_pos = sample_number - f->frame_start_sample;
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
628 return;
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
629 }
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
630 uint32_t best_seekpoint = f->num_seekpoints + 1;
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
631 if (f->num_seekpoints) {
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
632 uint64_t best_diff;
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
633 for (uint32_t i = 0; i < f->num_seekpoints; i++)
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
634 {
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
635 if (f->seekpoints[i].sample_number > sample_number) {
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
636 continue;
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
637 }
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
638 uint64_t diff = sample_number - f->seekpoints[i].sample_number;
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
639 if (best_seekpoint > f->num_seekpoints || diff < best_diff) {
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
640 best_seekpoint = i;
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
641 best_diff = diff;
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
642 }
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
643 }
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
644 }
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
645 //TODO: more efficient seeking
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
646 if (best_seekpoint > f->num_seekpoints) {
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
647 f->seek(f, f->first_frame_offset, 0);
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
648 } else if (f->seekpoints[best_seekpoint].sample_number > f->frame_start_sample || f->frame_start_sample > sample_number){
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
649 f->seek(f, f->seekpoints[best_seekpoint].offset + f->first_frame_offset, 0);
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
650 }
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
651 do {
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
652 if (!decode_frame(f)) {
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
653 return;
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
654 }
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
655 } while ((f->frame_start_sample + f->frame_block_size) <= sample_number);
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
656 f->frame_sample_pos = sample_number - f->frame_start_sample;
9d68799f945b Added basic FLAC seek implementation and added support for FLAC tracks in CUE sheets
Michael Pavone <pavone@retrodev.com>
parents: 2296
diff changeset
657 }