MCPcopy Create free account
hub / github.com/0xShug0/audio.cpp / ace_step_apply_repaint_waveform_splice

Function ace_step_apply_repaint_waveform_splice

src/models/ace_step/repaint.cpp:11–78  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

9namespace engine::models::ace_step {
10
11void ace_step_apply_repaint_waveform_splice(
12 runtime::AudioBuffer & decoded,
13 const AceStepRepaintSpliceSource & source,
14 float crossfade_seconds) {
15 if (decoded.sample_rate != kAceStepAudioSampleRate || source.audio.sample_rate != kAceStepAudioSampleRate ||
16 decoded.channels != kAceStepAudioChannels || source.audio.channels != kAceStepAudioChannels) {
17 throw std::runtime_error("ACE-Step repaint waveform splice requires stereo 48 kHz audio");
18 }
19 const int64_t decoded_frames =
20 static_cast<int64_t>(decoded.samples.size() / static_cast<size_t>(decoded.channels));
21 const int64_t source_frames =
22 static_cast<int64_t>(source.audio.samples.size() / static_cast<size_t>(source.audio.channels));
23 const int64_t frames = std::min(decoded_frames, source_frames);
24 if (frames <= 0) {
25 throw std::runtime_error("ACE-Step repaint waveform splice requires non-empty audio");
26 }
27
28 int64_t start_frame =
29 static_cast<int64_t>(static_cast<double>(source.start_seconds) * static_cast<double>(kAceStepAudioSampleRate));
30 int64_t end_frame =
31 static_cast<int64_t>(static_cast<double>(source.end_seconds) * static_cast<double>(kAceStepAudioSampleRate));
32 start_frame = std::max<int64_t>(0, std::min<int64_t>(start_frame, frames));
33 end_frame = std::max<int64_t>(start_frame, std::min<int64_t>(end_frame, frames));
34 if (start_frame == 0 && end_frame >= frames) {
35 return;
36 }
37
38 const int64_t crossfade_frames =
39 static_cast<int64_t>(static_cast<double>(crossfade_seconds) * static_cast<double>(kAceStepAudioSampleRate));
40 const int64_t fade_start = std::max<int64_t>(0, start_frame - std::max<int64_t>(0, crossfade_frames));
41 const int64_t fade_end = std::min<int64_t>(frames, end_frame + std::max<int64_t>(0, crossfade_frames));
42 const int64_t left_ramp_len = start_frame - fade_start;
43 const int64_t right_ramp_len = fade_end - end_frame;
44
45 if (fade_start > 0) {
46 std::copy(
47 source.audio.samples.begin(),
48 source.audio.samples.begin() + static_cast<std::ptrdiff_t>(fade_start * kAceStepAudioChannels),
49 decoded.samples.begin());
50 }
51 for (int64_t frame = fade_start; frame < start_frame; ++frame) {
52 const float mask = static_cast<float>(frame - fade_start + 1) / static_cast<float>(left_ramp_len + 1);
53 const size_t base = static_cast<size_t>(frame * kAceStepAudioChannels);
54 for (int channel = 0; channel < kAceStepAudioChannels; ++channel) {
55 const size_t index = base + static_cast<size_t>(channel);
56 decoded.samples[index] =
57 mask * decoded.samples[index] + (1.0F - mask) * source.audio.samples[index];
58 }
59 }
60 for (int64_t frame = end_frame; frame < fade_end; ++frame) {
61 const float mask = 1.0F - static_cast<float>(frame - end_frame + 1) / static_cast<float>(right_ramp_len + 1);
62 const size_t base = static_cast<size_t>(frame * kAceStepAudioChannels);
63 for (int channel = 0; channel < kAceStepAudioChannels; ++channel) {
64 const size_t index = base + static_cast<size_t>(channel);
65 decoded.samples[index] =
66 mask * decoded.samples[index] + (1.0F - mask) * source.audio.samples[index];
67 }
68 }

Callers 1

runMethod · 0.85

Calls 4

minFunction · 0.85
copyFunction · 0.85
sizeMethod · 0.45
beginMethod · 0.45

Tested by

no test coverage detected