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