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/graph_node.hpp>
8 #include <ossia/dataflow/nodes/media.hpp>
9 #include <ossia/dataflow/token_request.hpp>
11 #include <boost/circular_buffer.hpp>
13 #include <samplerate.h>
18 struct repitch_stretcher
20 struct resample_channel
22 resample_channel(
int buffersize) noexcept
23 : resampler{src_new(SRC_SINC_BEST_QUALITY, 1,
nullptr)}
24 , data(10 * buffersize)
27 resample_channel(resample_channel&& other) noexcept
28 : resampler{other.resampler}
29 , data{std::move(other.data)}
31 other.resampler =
nullptr;
33 resample_channel& operator=(resample_channel&& other) noexcept
35 resampler = other.resampler;
36 data = std::move(other.data);
37 other.resampler =
nullptr;
41 resample_channel(
const resample_channel&) =
delete;
42 resample_channel& operator=(
const resample_channel&) =
delete;
47 src_delete(resampler);
50 std::vector<float> input_buffer;
51 SRC_STATE* resampler{};
52 boost::circular_buffer<float> data;
55 repitch_stretcher(
int channels,
int bufferSize, int64_t pos)
56 : next_sample_to_read{pos}
58 repitchers.reserve(channels);
59 while(
int(repitchers.size()) < channels)
61 repitchers.emplace_back(bufferSize);
65 std::vector<float*> input_channels;
66 std::vector<float> output_buffer;
67 std::vector<resample_channel> repitchers;
68 int64_t next_sample_to_read{};
70 void transport(int64_t date) { next_sample_to_read = date; }
74 run(T& audio_fetcher,
const ossia::token_request& t, ossia::exec_state_facade e,
75 double tempo_ratio,
const std::size_t chan,
const int64_t len,
76 int64_t samples_to_read,
const int64_t samples_to_write,
77 const int64_t samples_offset,
const ossia::mutable_audio_span<double>& ap) noexcept
81 input_channels.resize(chan);
82 for(std::size_t i = 0; i < chan; i++)
84 repitchers[i].input_buffer.resize(
std::max((int64_t)16, samples_to_read));
85 input_channels[i] = repitchers[i].input_buffer.data();
87 output_buffer.resize(samples_to_write);
88 auto output = output_buffer.data();
90 int64_t num_samples_available = repitchers[0].data.size();
92 while(num_samples_available < samples_to_write)
94 audio_fetcher.fetch_audio(
95 next_sample_to_read, samples_to_read, input_channels.data());
98 for(std::size_t i = 0; i < chan; ++i)
100 data.data_in = repitchers[i].input_buffer.data();
101 data.data_out = output;
102 data.input_frames = samples_to_read;
103 data.output_frames = samples_to_write - num_samples_available;
104 data.input_frames_used = 0;
105 data.output_frames_gen = 0;
106 data.src_ratio = tempo_ratio;
107 data.end_of_input = 0;
110 src_process(repitchers[i].resampler, &data);
124 for(
int j = 0; j < data.output_frames_gen; j++)
125 repitchers[i].data.push_back(output[j]);
127 next_sample_to_read += data.input_frames_used;
128 samples_to_read = 16;
129 num_samples_available = repitchers[0].data.size();
132 for(std::size_t i = 0; i < chan; ++i)
134 auto it = repitchers[i].data.begin();
135 for(
int j = 0; j < samples_to_write; j++)
137 ap[i][j + samples_offset] = double(*it);
141 repitchers[i].data.erase_begin(samples_to_write);
149 #include <ossia/dataflow/nodes/timestretch/raw_stretcher.hpp>
153 using repitch_stretcher = raw_stretcher;
159 #include <ossia/dataflow/nodes/timestretch/raw_stretcher.hpp>
163 using repitch_stretcher = raw_stretcher;
constexpr OSSIA_INLINE auto max(const T a, const U b) noexcept -> typename std::conditional<(sizeof(T) > sizeof(U)), T, U >::type
max function tailored for values
Definition: math.hpp:96