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 #define _POSIX_C_SOURCE 199309L 20 21 #include <stdalign.h> 22 #include <stdio.h> 23 #include <stdarg.h> 24 #include <stdlib.h> 25 #include <string.h> 26 #include <math.h> 27 #include <time.h> 28 #include <errno.h> 29 30 #include <lc3.h> 31 #include "lc3bin.h" 32 #include "wave.h" 33 34 #define MAX_CHANNELS 2 35 36 #ifndef MIN 37 #define MIN(a, b) ( (a) < (b) ? (a) : (b) ) 38 #endif 39 40 #ifndef MAX 41 #define MAX(a, b) ( (a) > (b) ? (a) : (b) ) 42 #endif 43 44 45 /** 46 * Error handling 47 */ 48 49 static void error(int status, const char *format, ...) 50 { 51 va_list args; 52 53 fflush(stdout); 54 55 va_start(args, format); 56 vfprintf(stderr, format, args); 57 va_end(args); 58 59 fprintf(stderr, status ? ": %s\n" : "\n", strerror(status)); 60 exit(status); 61 } 62 63 64 /** 65 * Parameters 66 */ 67 68 struct parameters { 69 const char *fname_in; 70 const char *fname_out; 71 int bitdepth; 72 int srate_hz; 73 }; 74 75 static struct parameters parse_args(int argc, char *argv[]) 76 { 77 static const char *usage = 78 "Usage: %s [wav_file] [out_file]\n" 79 "\n" 80 "wav_file\t" "Input wave file, stdin if omitted\n" 81 "out_file\t" "Output bitstream file, stdout if omitted\n" 82 "\n" 83 "Options:\n" 84 "\t-h\t" "Display help\n" 85 "\t-b\t" "Output bitdepth, 16 bits (default) or 24 bits\n" 86 "\t-r\t" "Output samplerate, default is LC3 stream samplerate\n" 87 "\n"; 88 89 struct parameters p = { .bitdepth = 16 }; 90 91 for (int iarg = 1; iarg < argc; ) { 92 const char *arg = argv[iarg++]; 93 94 if (arg[0] == '-') { 95 if (arg[2] != '\0') 96 error(EINVAL, "Option %s", arg); 97 98 char opt = arg[1]; 99 const char *optarg = NULL; 100 101 switch (opt) { 102 case 'b': case 'r': 103 if (iarg >= argc) 104 error(EINVAL, "Argument %s", arg); 105 optarg = argv[iarg++]; 106 } 107 108 switch (opt) { 109 case 'h': fprintf(stderr, usage, argv[0]); exit(0); 110 case 'b': p.bitdepth = atoi(optarg); break; 111 case 'r': p.srate_hz = atoi(optarg); break; 112 default: 113 error(EINVAL, "Option %s", arg); 114 } 115 116 } else { 117 118 if (!p.fname_in) 119 p.fname_in = arg; 120 else if (!p.fname_out) 121 p.fname_out = arg; 122 else 123 error(EINVAL, "Argument %s", arg); 124 } 125 } 126 127 return p; 128 } 129 130 /** 131 * Return time in (us) from unspecified point in the past 132 */ 133 static unsigned clock_us(void) 134 { 135 struct timespec ts; 136 137 clock_gettime(CLOCK_REALTIME, &ts); 138 139 return (unsigned)(ts.tv_sec * 1000*1000) + (unsigned)(ts.tv_nsec / 1000); 140 } 141 142 /** 143 * Entry point 144 */ 145 int main(int argc, char *argv[]) 146 { 147 /* --- Read parameters --- */ 148 149 struct parameters p = parse_args(argc, argv); 150 FILE *fp_in = stdin, *fp_out = stdout; 151 152 if (p.fname_in && (fp_in = fopen(p.fname_in, "rb")) == NULL) 153 error(errno, "%s", p.fname_in); 154 155 if (p.fname_out && (fp_out = fopen(p.fname_out, "wb")) == NULL) 156 error(errno, "%s", p.fname_out); 157 158 if (p.bitdepth && p.bitdepth != 16 && p.bitdepth != 24) 159 error(EINVAL, "Bitdepth %d", p.bitdepth); 160 161 /* --- Check parameters --- */ 162 163 int frame_us, srate_hz, nchannels, nsamples; 164 bool hrmode; 165 166 if (lc3bin_read_header(fp_in, 167 &frame_us, &srate_hz, &hrmode, &nchannels, &nsamples) < 0) 168 error(EINVAL, "LC3 binary input file"); 169 170 if (nchannels < 1 || nchannels > MAX_CHANNELS) 171 error(EINVAL, "Number of channels %d", nchannels); 172 173 if (!LC3_CHECK_DT_US(frame_us)) 174 error(EINVAL, "Frame duration"); 175 176 if (!LC3_HR_CHECK_SR_HZ(hrmode, srate_hz)) 177 error(EINVAL, "Samplerate %d Hz", srate_hz); 178 179 if (p.srate_hz && (!LC3_HR_CHECK_SR_HZ(hrmode, p.srate_hz) || 180 p.srate_hz < srate_hz )) 181 error(EINVAL, "Output samplerate %d Hz", p.srate_hz); 182 183 int pcm_sbits = p.bitdepth; 184 int pcm_sbytes = pcm_sbits / 8; 185 186 int pcm_srate_hz = !p.srate_hz ? srate_hz : p.srate_hz; 187 int pcm_samples = !p.srate_hz ? nsamples : 188 ((int64_t)nsamples * pcm_srate_hz) / srate_hz; 189 190 wave_write_header(fp_out, 191 pcm_sbits, pcm_sbytes, pcm_srate_hz, nchannels, pcm_samples); 192 193 /* --- Setup decoding --- */ 194 195 uint8_t in[2 * LC3_HR_MAX_FRAME_BYTES]; 196 int8_t alignas(int32_t) pcm[2 * LC3_HR_MAX_FRAME_SAMPLES*4]; 197 lc3_decoder_t dec[2]; 198 199 int frame_samples = lc3_hr_frame_samples(hrmode, frame_us, pcm_srate_hz); 200 int encode_samples = pcm_samples + 201 lc3_hr_delay_samples(hrmode, frame_us, pcm_srate_hz); 202 enum lc3_pcm_format pcm_fmt = 203 pcm_sbits == 24 ? LC3_PCM_FORMAT_S24_3LE : LC3_PCM_FORMAT_S16; 204 205 for (int ich = 0; ich < nchannels; ich++) { 206 dec[ich] = lc3_hr_setup_decoder( 207 hrmode, frame_us, srate_hz, p.srate_hz, 208 malloc(lc3_hr_decoder_size(hrmode, frame_us, pcm_srate_hz))); 209 210 if (!dec[ich]) 211 error(EINVAL, "Decoder initialization failed"); 212 } 213 214 /* --- Decoding loop --- */ 215 216 static const char *dash_line = "========================================"; 217 218 int nsec = 0; 219 int nerr = 0; 220 unsigned t0 = clock_us(); 221 222 for (int i = 0; i * frame_samples < encode_samples; i++) { 223 224 int block_bytes = lc3bin_read_data(fp_in, nchannels, in); 225 226 if (floorf(i * frame_us * 1e-6) > nsec) { 227 228 float progress = fminf((float)i * frame_samples / pcm_samples, 1); 229 230 fprintf(stderr, "%02d:%02d [%-40s]\r", 231 nsec / 60, nsec % 60, 232 dash_line + (int)floorf((1 - progress) * 40)); 233 234 nsec = rint(i * frame_us * 1e-6); 235 } 236 237 if (block_bytes <= 0) 238 memset(pcm, 0, nchannels * frame_samples * pcm_sbytes); 239 else { 240 const uint8_t *in_ptr = in; 241 for (int ich = 0; ich < nchannels; ich++) { 242 int frame_bytes = block_bytes / nchannels 243 + (ich < block_bytes % nchannels); 244 245 int res = lc3_decode(dec[ich], in_ptr, frame_bytes, 246 pcm_fmt, pcm + ich * pcm_sbytes, nchannels); 247 248 nerr += (res != 0); 249 in_ptr += frame_bytes; 250 } 251 } 252 253 int pcm_offset = i > 0 ? 0 : encode_samples - pcm_samples; 254 int pcm_nwrite = MIN(frame_samples - pcm_offset, 255 encode_samples - i*frame_samples); 256 257 wave_write_pcm(fp_out, 258 pcm_sbytes, pcm, nchannels, pcm_offset, pcm_nwrite); 259 } 260 261 unsigned t = (clock_us() - t0) / 1000; 262 nsec = nsamples / srate_hz; 263 264 fprintf(stderr, "%02d:%02d Decoded in %d.%03d seconds %20s\n", 265 nsec / 60, nsec % 60, t / 1000, t % 1000, ""); 266 267 if (nerr) 268 fprintf(stderr, "Warning: Decoding of %d frames failed!\n", nerr); 269 270 /* --- Cleanup --- */ 271 272 for (int ich = 0; ich < nchannels; ich++) 273 free(dec[ich]); 274 275 if (fp_in != stdin) 276 fclose(fp_in); 277 278 if (fp_out != stdout) 279 fclose(fp_out); 280 } 281