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 epmode; 37 uint16_t nsamples_low; 38 uint16_t nsamples_high; 39 }; 40 41 42 /** 43 * Read LC3 binary header 44 */ 45 int lc3bin_read_header(FILE *fp, 46 int *frame_us, int *srate_hz, bool *hrmode, int *nchannels, int *nsamples) 47 { 48 struct lc3bin_header hdr; 49 uint16_t hdr_hrmode = 0; 50 51 if (fread(&hdr, sizeof(hdr), 1, fp) != 1 52 || hdr.file_id != LC3_FILE_ID 53 || hdr.header_size < sizeof(hdr)) 54 return -1; 55 56 int num_extended_params = (hdr.header_size - sizeof(hdr)) / sizeof(uint16_t); 57 if (num_extended_params >= 1 && 58 fread(&hdr_hrmode, sizeof(hdr_hrmode), 1, fp) != 1) 59 return -1; 60 61 *nchannels = hdr.channels; 62 *frame_us = hdr.frame_10us * 10; 63 *srate_hz = hdr.srate_100hz * 100; 64 *nsamples = hdr.nsamples_low | (hdr.nsamples_high << 16); 65 *hrmode = hdr_hrmode != 0; 66 67 if (hdr.epmode) 68 return -1; 69 70 fseek(fp, hdr.header_size, SEEK_SET); 71 72 return 0; 73 } 74 75 /** 76 * Read LC3 block of data 77 */ 78 int lc3bin_read_data(FILE *fp, int nchannels, void *buffer) 79 { 80 uint16_t nbytes; 81 82 if (fread(&nbytes, sizeof(nbytes), 1, fp) < 1 83 || nbytes > nchannels * LC3_HR_MAX_FRAME_BYTES 84 || fread(buffer, nbytes, 1, fp) < 1) 85 return -1; 86 87 return nbytes; 88 } 89 90 /** 91 * Write LC3 binary header 92 */ 93 void lc3bin_write_header(FILE *fp, 94 int frame_us, int srate_hz, bool hrmode, 95 int bitrate, int nchannels, int nsamples) 96 { 97 uint16_t hdr_hrmode = (hrmode != 0); 98 99 struct lc3bin_header hdr = { 100 .file_id = LC3_FILE_ID, 101 .header_size = sizeof(struct lc3bin_header) + 102 (hrmode ? sizeof(hdr_hrmode) : 0), 103 .srate_100hz = srate_hz / 100, 104 .bitrate_100bps = bitrate / 100, 105 .channels = nchannels, 106 .frame_10us = frame_us / 10, 107 .nsamples_low = nsamples & 0xffff, 108 .nsamples_high = nsamples >> 16, 109 }; 110 111 fwrite(&hdr, sizeof(hdr), 1, fp); 112 113 if (hrmode) 114 fwrite(&hdr_hrmode, sizeof(hdr_hrmode), 1, fp); 115 } 116 117 /** 118 * Write LC3 block of data 119 */ 120 void lc3bin_write_data(FILE *fp, const void *data, int nbytes) 121 { 122 uint16_t hdr_nbytes = nbytes; 123 fwrite(&hdr_nbytes, sizeof(hdr_nbytes), 1, fp); 124 125 fwrite(data, 1, nbytes, fp); 126 } 127