sample_rate_converter.cpp (3286B)
1 /** 2 * KFR (https://www.kfrlib.com) 3 * Copyright (C) 2016-2023 Dan Cazarin 4 * See LICENSE.txt for details 5 */ 6 7 #include <chrono> 8 #include <kfr/base.hpp> 9 #include <kfr/dsp.hpp> 10 #include <kfr/io.hpp> 11 12 // Example: Command line sample rate converter 13 14 using namespace kfr; 15 16 int main(int argc, char** argv) 17 { 18 println(library_version()); 19 if (argc < 4) 20 { 21 println("Usage: sample_rate_converter <INPUT_FILE> <OUTPUT_FILE> <TARGET_SAMPLE_RATE>"); 22 println("Supported formats: WAV/W64, 16, 24, 32-bit PCM, 32, 64-bit IEEE"); 23 return 1; 24 } 25 26 // Get output sample rate from the command line 27 const size_t output_sr = std::atol(argv[3]); 28 29 // Initialize WAV reader and get file sample rate 30 audio_reader_wav<double> reader(open_file_for_reading(argv[1])); 31 const size_t input_sr = static_cast<size_t>(reader.format().samplerate); 32 33 // Read channels of audio 34 univector2d<double> input_channels = reader.read_channels(reader.format().length); 35 36 // Prepare conversion 37 univector2d<double> output_channels; 38 println("Input channels: ", reader.format().channels); 39 println("Input sample rate: ", reader.format().samplerate); 40 println("Input bit depth: ", audio_sample_bit_depth(reader.format().type)); 41 42 for (size_t ch = 0; ch < input_channels.size(); ++ch) 43 { 44 println("Processing ", ch, " of ", reader.format().channels); 45 const univector<double>& input = input_channels[ch]; 46 47 // Initialize resampler 48 auto r = resampler<double>(resample_quality::high, output_sr, input_sr); 49 50 // Calculate output size and initialize output buffer 51 const size_t output_size = input.size() * output_sr / input_sr; 52 univector<double> output(output_size); 53 54 // Skip the first r.get_delay() samples (FIR filter delay). Returns new input pos 55 size_t input_pos = r.skip(r.get_delay(), input.slice()); 56 57 std::chrono::high_resolution_clock::time_point start_time = std::chrono::high_resolution_clock::now(); 58 size_t output_pos = 0; 59 for (;;) 60 { 61 const size_t block_size = std::min(size_t(16384), output.size() - output_pos); 62 if (block_size == 0) 63 break; 64 65 // Process new block of audio 66 input_pos += r.process(output.slice(output_pos, block_size).ref(), input.slice(input_pos)); 67 output_pos += block_size; 68 } 69 70 std::chrono::high_resolution_clock::duration time = 71 std::chrono::high_resolution_clock::now() - start_time; 72 const double duration = static_cast<double>(output.size()) / output_sr; 73 println("time: ", 74 fmt<'f', 6, 2>(std::chrono::duration_cast<std::chrono::microseconds>(time).count() / 75 duration * 0.001), 76 "ms per 1 second of audio"); 77 78 // Place buffer to the list of output channels 79 output_channels.push_back(std::move(output)); 80 } 81 82 // Initialize WAV writer 83 audio_writer_wav<double> writer( 84 open_file_for_writing(argv[2]), 85 audio_format{ reader.format().channels, reader.format().type, kfr::fmax(output_sr) }); 86 87 // Write audio 88 writer.write_channels(output_channels); 89 90 return 0; 91 }