22 halp_meta(name,
"Audio recorder")
23 halp_meta(author,
"ossia team")
24 halp_meta(category,
"Audio/Recording")
25 halp_meta(description,
"Records audio to a file")
26 halp_meta(c_name,
"avnd_audio_recorder")
29 "https://ossia.io/score-docs/processes/audio-utilities.html#audio-recorder")
30 halp_meta(uuid,
"4463dddc-6acf-4106-a680-fed67d8030da")
32 using audio_buffer = boost::container::vector<double>;
42 ossia::drwav_write_handle f;
44 std::string actual_filename;
47 bool must_record =
false;
54 auto fname = QString::fromStdString(this->filename);
56 fname.replace(
"%t", QDateTime::currentDateTimeUtc().toString());
58 actual_filename = fname.toStdString();
59 f.open(actual_filename, channels, rate, 16);
64 bool must_reply =
false;
65 if(f.is_open() && f.written_frames() > 0)
74 void write(
int frames, audio_buffer& data)
76 int these_channels = data.size() / frames;
77 if(these_channels != channels)
79 channels = these_channels;
88 const double** arr = (
const double**)alloca(channels *
sizeof(
double*));
89 for(
int c = 0; c < channels; ++c)
90 arr[c] = data.data() + c * frames;
93 f.write_pcm_frames(frames, arr);
96 std::shared_ptr<recorder_thread> impl;
106 swap(self.filename, path);
108 self.must_record = must_record;
109 return self.reopen();
119 self.write(frames, data);
123 using worker_message = ossia::variant<reset_message, process_message>;
127 std::function<void(std::shared_ptr<recorder_thread>, worker_message)> request;
129 work(std::shared_ptr<recorder_thread> t, worker_message&& mess)
131 bool reply = ossia::visit(
132 [&]<
typename M>(M&& msg) {
return std::forward<M>(msg)(*t); },
136 return [filename = t->actual_filename](
AudioRecorder& self)
mutable {
138 swap(self.filename_to_output, filename);
151 halp::dynamic_audio_bus<
"Audio",
double> audio;
152 struct : halp::lineedit<
"File pattern",
"">
154 void update(AudioRecorder& self) { self.update(); }
157 struct : halp::toggle<
"Record">
159 void update(AudioRecorder& self)
173 halp::callback<
"Filename", std::string> finished;
177 int current_rate = 0;
178 void prepare(halp::setup s)
180 current_rate = s.rate;
181 SCORE_ASSERT(ossia_document_context);
182 impl = std::make_shared<recorder_thread>(*ossia_document_context);
189 worker.request(impl, reset_message{inputs.filename, current_rate, inputs.record});
192 void operator()(
int frames)
194 if(!std::exchange(started,
true))
197 data.resize(inputs.audio.channels * frames, boost::container::default_init);
198 for(
int c = 0; c < inputs.audio.channels; c++)
200 double* src = inputs.audio.samples[c];
201 double* ptr = data.data() + c * frames;
202 for(
int i = 0; i < frames; i++)
206 worker.request(impl, process_message{frames, std::move(data)});
208 if(!filename_to_output.empty())
210 outputs.finished(filename_to_output);
211 filename_to_output.clear();
216 std::optional<int64_t> first_message_sent_pos;
217 std::optional<int64_t> last_message_sent_pos;
220 std::string filename_to_output;
Definition DocumentContext.hpp:18