2#include <ossia/detail/config.hpp> 
    4#if defined(OSSIA_ENABLE_LIBSAMPLERATE) 
    5#if __has_include(<samplerate.h>) 
    6#include <ossia/dataflow/audio_port.hpp> 
    7#include <ossia/dataflow/audio_stretch_mode.hpp> 
    8#include <ossia/dataflow/graph_node.hpp> 
    9#include <ossia/dataflow/nodes/media.hpp> 
   10#include <ossia/dataflow/token_request.hpp> 
   12#include <boost/circular_buffer.hpp> 
   14#include <samplerate.h> 
   19static constexpr auto get_samplerate_preset(ossia::audio_stretch_mode mode)
 
   21  int qmode = SRC_SINC_BEST_QUALITY;
 
   22  if(mode == audio_stretch_mode::RepitchMediumQ)
 
   23    qmode = SRC_SINC_FASTEST;
 
   24  if(mode == audio_stretch_mode::RepitchFastestQ)
 
   29struct repitch_stretcher
 
   31  struct resample_channel
 
   33    explicit resample_channel(
int preset, 
int buffersize) noexcept
 
   34        : resampler{src_new(preset, 1, 
nullptr)}
 
   35        , data(10 * buffersize)
 
   38    resample_channel(resample_channel&& other) noexcept
 
   39        : resampler{other.resampler}
 
   40        , data{std::move(other.data)}
 
   42      other.resampler = 
nullptr;
 
   44    resample_channel& operator=(resample_channel&& other) 
noexcept 
   46      resampler = other.resampler;
 
   47      data = std::move(other.data);
 
   48      other.resampler = 
nullptr;
 
   52    resample_channel(
const resample_channel&) = 
delete;
 
   53    resample_channel& operator=(
const resample_channel&) = 
delete;
 
   58        src_delete(resampler);
 
   61    std::vector<float> input_buffer;
 
   62    SRC_STATE* resampler{};
 
   63    boost::circular_buffer<float> data;
 
   66  repitch_stretcher(
int preset, 
int channels, 
int bufferSize, int64_t pos)
 
   67      : next_sample_to_read{pos}
 
   70    repitchers.reserve(channels);
 
   71    while(
int(repitchers.size()) < channels)
 
   73      repitchers.emplace_back(preset, bufferSize);
 
   77  std::vector<float*> input_channels;
 
   78  std::vector<float> output_buffer;
 
   79  std::vector<resample_channel> repitchers;
 
   80  int64_t next_sample_to_read{};
 
   83  void transport(int64_t date) { next_sample_to_read = date; }
 
   87  run(T& audio_fetcher, 
const ossia::token_request& t, ossia::exec_state_facade e,
 
   88      double tempo_ratio, 
const std::size_t chan, 
const int64_t len,
 
   89      int64_t samples_to_read, 
const int64_t samples_to_write,
 
   90      const int64_t samples_offset, 
const ossia::mutable_audio_span<double>& ap) 
noexcept 
   94    input_channels.resize(chan);
 
   95    for(std::size_t i = 0; i < chan; i++)
 
   97      repitchers[i].input_buffer.resize(std::max((int64_t)16, samples_to_read));
 
   98      input_channels[i] = repitchers[i].input_buffer.data();
 
  100    output_buffer.resize(samples_to_write);
 
  101    auto output = output_buffer.data();
 
  103    int64_t num_samples_available = repitchers[0].data.size();
 
  105    while(num_samples_available < samples_to_write)
 
  107      audio_fetcher.fetch_audio(
 
  108          next_sample_to_read, samples_to_read, input_channels.data());
 
  111      for(std::size_t i = 0; i < chan; ++i)
 
  113        data.data_in = repitchers[i].input_buffer.data();
 
  114        data.data_out = output;
 
  115        data.input_frames = samples_to_read;
 
  116        data.output_frames = samples_to_write - num_samples_available;
 
  117        data.input_frames_used = 0;
 
  118        data.output_frames_gen = 0;
 
  119        data.src_ratio = tempo_ratio;
 
  120        data.end_of_input = 0;
 
  123        src_process(repitchers[i].resampler, &data);
 
  137        for(
int j = 0; j < data.output_frames_gen; j++)
 
  138          repitchers[i].data.push_back(output[j]);
 
  140      next_sample_to_read += data.input_frames_used;
 
  141      samples_to_read = 16;
 
  142      num_samples_available = repitchers[0].data.size();
 
  145    for(std::size_t i = 0; i < chan; ++i)
 
  147      auto it = repitchers[i].data.begin();
 
  148      for(
int j = 0; j < samples_to_write; j++)
 
  150        ap[i][j + samples_offset] = double(*it);
 
  154      repitchers[i].data.erase_begin(samples_to_write);
 
  162#include <ossia/dataflow/nodes/timestretch/raw_stretcher.hpp> 
  166static constexpr int get_samplerate_preset(ossia::audio_stretch_mode mode)
 
  170using repitch_stretcher = raw_stretcher;
 
  176#include <ossia/dataflow/nodes/timestretch/raw_stretcher.hpp> 
  180static constexpr int get_samplerate_preset(ossia::audio_stretch_mode mode)
 
  184using repitch_stretcher = raw_stretcher;