xref: /btstack/3rd-party/lc3-google/tools/lc3bin.c (revision 6897da5c53aac5b1f90f41b5b15d0bd43d61dfff)
14930cef6SMatthias Ringwald /******************************************************************************
24930cef6SMatthias Ringwald  *
34930cef6SMatthias Ringwald  *  Copyright 2022 Google LLC
44930cef6SMatthias Ringwald  *
54930cef6SMatthias Ringwald  *  Licensed under the Apache License, Version 2.0 (the "License");
64930cef6SMatthias Ringwald  *  you may not use this file except in compliance with the License.
74930cef6SMatthias Ringwald  *  You may obtain a copy of the License at:
84930cef6SMatthias Ringwald  *
94930cef6SMatthias Ringwald  *  http://www.apache.org/licenses/LICENSE-2.0
104930cef6SMatthias Ringwald  *
114930cef6SMatthias Ringwald  *  Unless required by applicable law or agreed to in writing, software
124930cef6SMatthias Ringwald  *  distributed under the License is distributed on an "AS IS" BASIS,
134930cef6SMatthias Ringwald  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
144930cef6SMatthias Ringwald  *  See the License for the specific language governing permissions and
154930cef6SMatthias Ringwald  *  limitations under the License.
164930cef6SMatthias Ringwald  *
174930cef6SMatthias Ringwald  ******************************************************************************/
184930cef6SMatthias Ringwald 
194930cef6SMatthias Ringwald #include <stdint.h>
204930cef6SMatthias Ringwald #include "lc3bin.h"
214930cef6SMatthias Ringwald 
224930cef6SMatthias Ringwald 
234930cef6SMatthias Ringwald /**
244930cef6SMatthias Ringwald  * LC3 binary header
254930cef6SMatthias Ringwald  */
264930cef6SMatthias Ringwald 
274930cef6SMatthias Ringwald #define LC3_FILE_ID (0x1C | (0xCC << 8))
284930cef6SMatthias Ringwald 
294930cef6SMatthias Ringwald struct lc3bin_header {
304930cef6SMatthias Ringwald     uint16_t file_id;
314930cef6SMatthias Ringwald     uint16_t header_size;
324930cef6SMatthias Ringwald     uint16_t srate_100hz;
334930cef6SMatthias Ringwald     uint16_t bitrate_100bps;
344930cef6SMatthias Ringwald     uint16_t channels;
354930cef6SMatthias Ringwald     uint16_t frame_10us;
36*6897da5cSDirk Helbig     uint16_t epmode;
374930cef6SMatthias Ringwald     uint16_t nsamples_low;
384930cef6SMatthias Ringwald     uint16_t nsamples_high;
394930cef6SMatthias Ringwald };
404930cef6SMatthias Ringwald 
414930cef6SMatthias Ringwald 
424930cef6SMatthias Ringwald /**
434930cef6SMatthias Ringwald  * Read LC3 binary header
444930cef6SMatthias Ringwald  */
lc3bin_read_header(FILE * fp,int * frame_us,int * srate_hz,bool * hrmode,int * nchannels,int * nsamples)454930cef6SMatthias Ringwald int lc3bin_read_header(FILE *fp,
46*6897da5cSDirk Helbig     int *frame_us, int *srate_hz, bool *hrmode, int *nchannels, int *nsamples)
474930cef6SMatthias Ringwald {
484930cef6SMatthias Ringwald     struct lc3bin_header hdr;
49*6897da5cSDirk Helbig     uint16_t hdr_hrmode = 0;
504930cef6SMatthias Ringwald 
514930cef6SMatthias Ringwald     if (fread(&hdr, sizeof(hdr), 1, fp) != 1
52*6897da5cSDirk Helbig             || hdr.file_id != LC3_FILE_ID
53*6897da5cSDirk Helbig             || hdr.header_size < sizeof(hdr))
54*6897da5cSDirk Helbig         return -1;
55*6897da5cSDirk Helbig 
56*6897da5cSDirk Helbig     int num_extended_params = (hdr.header_size - sizeof(hdr)) / sizeof(uint16_t);
57*6897da5cSDirk Helbig     if (num_extended_params >= 1 &&
58*6897da5cSDirk Helbig         fread(&hdr_hrmode, sizeof(hdr_hrmode), 1, fp) != 1)
594930cef6SMatthias Ringwald       return -1;
604930cef6SMatthias Ringwald 
614930cef6SMatthias Ringwald     *nchannels = hdr.channels;
624930cef6SMatthias Ringwald     *frame_us = hdr.frame_10us * 10;
634930cef6SMatthias Ringwald     *srate_hz = hdr.srate_100hz * 100;
644930cef6SMatthias Ringwald     *nsamples = hdr.nsamples_low | (hdr.nsamples_high << 16);
65*6897da5cSDirk Helbig     *hrmode = hdr_hrmode != 0;
664930cef6SMatthias Ringwald 
67*6897da5cSDirk Helbig     if (hdr.epmode)
68*6897da5cSDirk Helbig       return -1;
69*6897da5cSDirk Helbig 
70*6897da5cSDirk Helbig     fseek(fp, hdr.header_size, SEEK_SET);
714930cef6SMatthias Ringwald 
724930cef6SMatthias Ringwald     return 0;
734930cef6SMatthias Ringwald }
744930cef6SMatthias Ringwald 
754930cef6SMatthias Ringwald /**
764930cef6SMatthias Ringwald  * Read LC3 block of data
774930cef6SMatthias Ringwald  */
lc3bin_read_data(FILE * fp,int nchannels,void * buffer)784930cef6SMatthias Ringwald int lc3bin_read_data(FILE *fp, int nchannels, void *buffer)
794930cef6SMatthias Ringwald {
804930cef6SMatthias Ringwald     uint16_t nbytes;
814930cef6SMatthias Ringwald 
824930cef6SMatthias Ringwald     if (fread(&nbytes, sizeof(nbytes), 1, fp) < 1
83*6897da5cSDirk Helbig             || nbytes > nchannels * LC3_HR_MAX_FRAME_BYTES
844930cef6SMatthias Ringwald             || fread(buffer, nbytes, 1, fp) < 1)
854930cef6SMatthias Ringwald         return -1;
864930cef6SMatthias Ringwald 
87*6897da5cSDirk Helbig     return nbytes;
884930cef6SMatthias Ringwald }
894930cef6SMatthias Ringwald 
904930cef6SMatthias Ringwald /**
914930cef6SMatthias Ringwald  * Write LC3 binary header
924930cef6SMatthias Ringwald  */
lc3bin_write_header(FILE * fp,int frame_us,int srate_hz,bool hrmode,int bitrate,int nchannels,int nsamples)934930cef6SMatthias Ringwald void lc3bin_write_header(FILE *fp,
94*6897da5cSDirk Helbig     int frame_us, int srate_hz, bool hrmode,
95*6897da5cSDirk Helbig     int bitrate, int nchannels, int nsamples)
964930cef6SMatthias Ringwald {
97*6897da5cSDirk Helbig     uint16_t hdr_hrmode = (hrmode != 0);
98*6897da5cSDirk Helbig 
994930cef6SMatthias Ringwald     struct lc3bin_header hdr = {
1004930cef6SMatthias Ringwald         .file_id = LC3_FILE_ID,
101*6897da5cSDirk Helbig         .header_size = sizeof(struct lc3bin_header) +
102*6897da5cSDirk Helbig             (hrmode ? sizeof(hdr_hrmode) : 0),
1034930cef6SMatthias Ringwald         .srate_100hz = srate_hz / 100,
1044930cef6SMatthias Ringwald         .bitrate_100bps = bitrate / 100,
1054930cef6SMatthias Ringwald         .channels = nchannels,
1064930cef6SMatthias Ringwald         .frame_10us = frame_us / 10,
1074930cef6SMatthias Ringwald         .nsamples_low = nsamples & 0xffff,
1084930cef6SMatthias Ringwald         .nsamples_high = nsamples >> 16,
1094930cef6SMatthias Ringwald     };
1104930cef6SMatthias Ringwald 
1114930cef6SMatthias Ringwald     fwrite(&hdr, sizeof(hdr), 1, fp);
112*6897da5cSDirk Helbig 
113*6897da5cSDirk Helbig     if (hrmode)
114*6897da5cSDirk Helbig         fwrite(&hdr_hrmode, sizeof(hdr_hrmode), 1, fp);
1154930cef6SMatthias Ringwald }
1164930cef6SMatthias Ringwald 
1174930cef6SMatthias Ringwald /**
1184930cef6SMatthias Ringwald  * Write LC3 block of data
1194930cef6SMatthias Ringwald  */
lc3bin_write_data(FILE * fp,const void * data,int nbytes)120*6897da5cSDirk Helbig void lc3bin_write_data(FILE *fp, const void *data, int nbytes)
1214930cef6SMatthias Ringwald {
122*6897da5cSDirk Helbig     uint16_t hdr_nbytes = nbytes;
123*6897da5cSDirk Helbig     fwrite(&hdr_nbytes, sizeof(hdr_nbytes), 1, fp);
1244930cef6SMatthias Ringwald 
1254930cef6SMatthias Ringwald     fwrite(data, 1, nbytes, fp);
1264930cef6SMatthias Ringwald }
127