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