kfr

Fast, modern C++ DSP framework, FFT, Sample Rate Conversion, FIR/IIR/Biquad Filters (SSE, AVX, AVX-512, ARM NEON)
Log | Files | Refs | README

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 }