1 /******************************************************************************
2 *
3 * Copyright 2022 Google LLC
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19 #include <stdint.h>
20 #include "lc3bin.h"
21
22
23 /**
24 * LC3 binary header
25 */
26
27 #define LC3_FILE_ID (0x1C | (0xCC << 8))
28
29 struct lc3bin_header {
30 uint16_t file_id;
31 uint16_t header_size;
32 uint16_t srate_100hz;
33 uint16_t bitrate_100bps;
34 uint16_t channels;
35 uint16_t frame_10us;
36 uint16_t rfu;
37 uint16_t nsamples_low;
38 uint16_t nsamples_high;
39 };
40
41
42 /**
43 * Read LC3 binary header
44 */
lc3bin_read_header(FILE * fp,int * frame_us,int * srate_hz,int * nchannels,int * nsamples)45 int lc3bin_read_header(FILE *fp,
46 int *frame_us, int *srate_hz, int *nchannels, int *nsamples)
47 {
48 struct lc3bin_header hdr;
49
50 if (fread(&hdr, sizeof(hdr), 1, fp) != 1
51 || hdr.file_id != LC3_FILE_ID)
52 return -1;
53
54 *nchannels = hdr.channels;
55 *frame_us = hdr.frame_10us * 10;
56 *srate_hz = hdr.srate_100hz * 100;
57 *nsamples = hdr.nsamples_low | (hdr.nsamples_high << 16);
58
59 fseek(fp, SEEK_SET, hdr.header_size);
60
61 return 0;
62 }
63
64 /**
65 * Read LC3 block of data
66 */
lc3bin_read_data(FILE * fp,int nchannels,void * buffer)67 int lc3bin_read_data(FILE *fp, int nchannels, void *buffer)
68 {
69 uint16_t nbytes;
70
71 if (fread(&nbytes, sizeof(nbytes), 1, fp) < 1
72 || nbytes > nchannels * LC3_MAX_FRAME_BYTES
73 || nbytes % nchannels
74 || fread(buffer, nbytes, 1, fp) < 1)
75 return -1;
76
77 return nbytes / nchannels;
78 }
79
80 /**
81 * Write LC3 binary header
82 */
lc3bin_write_header(FILE * fp,int frame_us,int srate_hz,int bitrate,int nchannels,int nsamples)83 void lc3bin_write_header(FILE *fp,
84 int frame_us, int srate_hz, int bitrate, int nchannels, int nsamples)
85 {
86 struct lc3bin_header hdr = {
87 .file_id = LC3_FILE_ID,
88 .header_size = sizeof(struct lc3bin_header),
89 .srate_100hz = srate_hz / 100,
90 .bitrate_100bps = bitrate / 100,
91 .channels = nchannels,
92 .frame_10us = frame_us / 10,
93 .nsamples_low = nsamples & 0xffff,
94 .nsamples_high = nsamples >> 16,
95 };
96
97 fwrite(&hdr, sizeof(hdr), 1, fp);
98 }
99
100 /**
101 * Write LC3 block of data
102 */
lc3bin_write_data(FILE * fp,const void * data,int nchannels,int frame_bytes)103 void lc3bin_write_data(FILE *fp,
104 const void *data, int nchannels, int frame_bytes)
105 {
106 uint16_t nbytes = nchannels * frame_bytes;
107 fwrite(&nbytes, sizeof(nbytes), 1, fp);
108
109 fwrite(data, 1, nbytes, fp);
110 }
111