rawdio/effects/recorder/
recorder_node.rs1use super::{recorder_event::*, recorder_notification::*, recorder_processor::RecorderProcessor};
2use crate::{
3 commands::Id, effects::Channel, engine::NotifierStatus, graph::DspParameters, prelude::*,
4};
5use std::{cell::RefCell, rc::Rc};
6
7pub struct Recorder {
14 pub node: GraphNode,
16 event_transmitter: RecorderEventTransmitter,
17 notification_receiver: RecorderNotificationReceiver,
18 current_recording: Option<OwnedAudioBuffer>,
19 is_recording: bool,
20}
21
22static EVENT_CHANNEL_CAPACITY: usize = 32;
23static NOTIFICATION_CHANNEL_CAPACITY: usize = 32;
24
25impl Recorder {
26 pub fn new(
28 context: &mut dyn Context,
29 channel_count: usize,
30 sample_rate: usize,
31 ) -> Rc<RefCell<Self>> {
32 let id = Id::generate();
33
34 let (event_transmitter, event_receiver) = Channel::bounded(EVENT_CHANNEL_CAPACITY);
35 let (notification_transmitter, notification_receiver) =
36 Channel::bounded(NOTIFICATION_CHANNEL_CAPACITY);
37
38 let processor = Box::new(RecorderProcessor::new(
39 sample_rate,
40 channel_count,
41 event_receiver,
42 notification_transmitter,
43 ));
44
45 let output_count = 0;
46
47 let node = GraphNode::new(
48 id,
49 context,
50 channel_count,
51 output_count,
52 processor,
53 DspParameters::empty(),
54 );
55
56 let recorder = Rc::new(RefCell::new(Self {
57 node,
58 event_transmitter,
59 notification_receiver,
60 current_recording: None,
61 is_recording: false,
62 }));
63
64 let weak_recorder = Rc::downgrade(&recorder);
65
66 context.add_notifier(Box::new(move || {
67 if let Some(recorder) = weak_recorder.upgrade() {
68 recorder.borrow_mut().process_notifications();
69 return NotifierStatus::Continue;
70 }
71
72 NotifierStatus::Remove
73 }));
74
75 recorder
76 }
77
78 pub fn record_now(&mut self) {
80 let _ = self.event_transmitter.send(RecorderEvent::start_now());
81 }
82
83 pub fn stop_record_now(&mut self) {
85 let _ = self.event_transmitter.send(RecorderEvent::stop_now());
86 }
87
88 pub fn stop_record_at_time(&mut self, time: Timestamp) {
90 let _ = self
91 .event_transmitter
92 .send(RecorderEvent::stop_at_time(time));
93 }
94
95 pub fn is_recording(&self) -> bool {
97 self.is_recording
98 }
99
100 pub fn take_recording(&mut self) -> Option<OwnedAudioBuffer> {
104 self.current_recording.take()
105 }
106
107 fn append_buffer(&mut self, buffer: &OwnedAudioBuffer, samples_used: usize) {
108 let slice = BorrowedAudioBuffer::slice_frames(buffer, 0, samples_used);
109 self.current_recording = match &self.current_recording {
110 Some(current_recording) => Some(current_recording.extended_with_buffer(&slice)),
111 None => Some(OwnedAudioBuffer::from_buffer(&slice)),
112 };
113 }
114
115 fn return_buffer(&mut self, buffer: OwnedAudioBuffer) {
116 let _ = self
117 .event_transmitter
118 .send(RecorderEvent::return_buffer(buffer));
119 }
120
121 fn process_notifications(&mut self) {
122 while let Ok(event) = self.notification_receiver.try_recv() {
123 match event {
124 RecorderNotification::Start => self.is_recording = true,
125 RecorderNotification::Data(buffer, samples_used) => {
126 self.append_buffer(&buffer, samples_used);
127 self.return_buffer(buffer);
128 }
129 RecorderNotification::Stop => self.is_recording = false,
130 }
131 }
132 }
133}