34 std::string_view path_utf8,
int channels,
int rate, int64_t frames,
37 if(channels <= 0 || rate <= 0 || frames < 0 || path_utf8.empty())
40 const std::filesystem::path path{std::u8string_view{
41 reinterpret_cast<const char8_t*
>(path_utf8.data()), path_utf8.size()}};
42 std::ofstream file{path, std::ios::binary | std::ios::trunc};
49 std::filesystem::remove(path, ec);
54 constexpr uint64_t riff_max_data = 0xFFFFFFFFull - 65536;
55 const uint64_t data_bytes = uint64_t(frames) * uint64_t(channels) *
sizeof(float);
57 drwav_data_format format{};
59 = data_bytes > riff_max_data ? drwav_container_rf64 : drwav_container_riff;
60 format.format = DR_WAVE_FORMAT_IEEE_FLOAT;
61 format.channels = channels;
62 format.sampleRate = rate;
63 format.bitsPerSample = 32;
65 drwav_metadata metadata[2]{};
66 drwav_uint32 metadata_count = 0;
70 drwav_smpl_loop sampler_loop{};
71 if(info.loop && frames > 0 && uint64_t(frames - 1) <= 0xFFFFFFFFull)
73 sampler_loop.type = drwav_smpl_loop_type_forward;
74 sampler_loop.firstSampleOffset = 0;
75 sampler_loop.lastSampleOffset = drwav_uint32(frames - 1);
77 auto& smpl = metadata[metadata_count++];
78 smpl.type = drwav_metadata_type_smpl;
79 smpl.data.smpl.samplePeriodNanoseconds = drwav_uint32(1e9 / rate);
80 smpl.data.smpl.midiUnityNote = 60;
81 smpl.data.smpl.sampleLoopCount = 1;
82 smpl.data.smpl.pLoops = &sampler_loop;
87 auto& acid = metadata[metadata_count++];
88 acid.type = drwav_metadata_type_acid;
89 acid.data.acid.flags = info.loop ? drwav_acid_flag_stretch : drwav_acid_flag_one_shot;
90 acid.data.acid.midiUnityNote = 60;
91 acid.data.acid.reserved1 = 0x80;
92 acid.data.acid.numBeats = drwav_uint32(info.beats > 0 ? info.beats : 0);
93 acid.data.acid.meterNumerator = drwav_uint16(info.meter_numerator);
94 acid.data.acid.meterDenominator = drwav_uint16(info.meter_denominator);
95 acid.data.acid.tempo = float(info.tempo);
98 auto on_write = [](
void* user,
const void* src,
size_t bytes) ->
size_t {
99 auto& f = *
static_cast<std::ofstream*
>(user);
100 f.write(
static_cast<const char*
>(src), std::streamsize(bytes));
101 return f ? bytes : 0;
103 auto on_seek = [](
void* user,
int offset, drwav_seek_origin origin) -> drwav_bool32 {
104 auto& f = *
static_cast<std::ofstream*
>(user);
108 f.seekp(offset, std::ios::beg);
111 f.seekp(offset, std::ios::cur);
114 f.seekp(offset, std::ios::end);
121 if(!drwav_init_write_with_metadata(
122 &wav, &format, on_write, on_seek, &file,
nullptr,
123 metadata_count > 0 ? metadata :
nullptr, metadata_count))
126 constexpr int64_t chunk = 4096;
127 std::vector<float> interleaved(std::size_t(chunk * channels));
129 while(written < frames)
131 const int64_t n = std::min(chunk, frames - written);
132 for(int64_t i = 0; i < n; i++)
133 for(
int c = 0; c < channels; c++)
134 interleaved[std::size_t(i * channels + c)] = data[c][written + i];
135 if(drwav_write_pcm_frames(&wav, drwav_uint64(n), interleaved.data()) != drwav_uint64(n))
140 const bool finalized = drwav_uninit(&wav) == DRWAV_SUCCESS;
142 if(written != frames || !finalized || !file)
bool write_loop_wav(std::string_view path_utf8, int channels, int rate, int64_t frames, const float *const *data, const wav_loop_info &info)
Writes frames frames of 32-bit float audio, one pointer per channel, to a WAV file with the loop meta...
Definition write_loop_wav.hpp:33