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