redact_composer_core/
lib.rs

1#![deny(missing_docs, missing_debug_implementations)]
2//! Core library for `redact_composer`. Lib-level crates should depend on this rather than the
3//! application-level `redact_composer`.
4
5extern crate self as redact_composer_core;
6
7/// Error types.
8pub mod error;
9
10/// Types and traits used for and during composition rendering.
11pub mod render;
12
13/// Timing related structs and elements.
14pub mod timing;
15/// Re-exports of non-deterministic [`std::collections`], with deterministic defaults.
16pub mod util;
17
18#[cfg(test)]
19mod test;
20
21use rand::{thread_rng, RngCore, SeedableRng};
22use rand_chacha::ChaCha12Rng;
23use std::any::TypeId;
24use std::collections::{Bound, HashSet};
25use std::fmt::Debug;
26use std::hash::{Hash, Hasher};
27use std::iter::successors;
28use std::ops::{Range, RangeBounds};
29use twox_hash::XxHash64;
30
31#[cfg(feature = "serde")]
32use serde::{Deserialize, Serialize};
33
34use crate::error::ConversionError;
35use crate::render::context::CompositionContext;
36use crate::render::{tree::Tree, RenderEngine, RenderSegment};
37use crate::timing::{Timing, STANDARD_BEAT_LENGTH};
38
39/// Contains the derive macro of [`Element`]. Specifically kept separate in core, so
40/// exporting trait vs macro can be done separately
41pub mod derive {
42    pub use redact_composer_derive::ElementCore as Element;
43}
44
45use std::any::Any;
46
47const LOG: &str = "redact_composer";
48
49/// Marker trait for any type that will be used as a composition element.
50///
51/// Can be implemented via its derive macro:
52/// ```no_run
53/// # use serde::{Deserialize, Serialize};
54/// # use redact_composer_core::derive::Element;
55/// # #[derive(Debug, Serialize, Deserialize)]
56/// #[derive(Element)]
57/// pub struct CustomCompositionElement;
58/// ```
59///
60/// If implementing maually, remember to tag the impl block with `#[typetag::serde]` for proper
61/// serialization behavior.
62///
63/// **Advanced**: Overriding the default [`wrapped_element`](crate::Element::wrapped_element) method
64/// indicates another element this one wraps. Wrapped elements will render alongside their wrappers,
65/// producing a cumulative set of children. Mainly used to provide a common 'tag' type for an
66/// unknown set of other elements, enabling context lookups or other operations that depend on
67/// element type.
68#[cfg_attr(feature = "serde", typetag::serde)]
69pub trait Element: Debug + AsAny + 'static {
70    /// None.
71    fn wrapped_element(&self) -> Option<&dyn Element> {
72        None
73    }
74}
75
76/// Convenience trait for converting to [`&dyn Any`].
77pub trait AsAny {
78    /// Converts this to a [`&dyn Any`].
79    fn as_any(&self) -> &dyn Any;
80}
81
82impl<T: Element> AsAny for T {
83    fn as_any(&self) -> &dyn Any {
84        self
85    }
86}
87
88/// A (type-erased) [`Element`] spanning a [`Timing`] interval.
89#[derive(Debug)]
90#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
91pub struct Segment {
92    /// The element this segment represents.
93    pub element: Box<dyn Element>,
94    /// The timing interval this segment spans.
95    #[cfg_attr(feature = "serde", serde(flatten))]
96    pub timing: Timing,
97    /// An optional name. When being rendered, this segment's Rng are seeded with a combined hash of
98    /// this name as well as the segment's parent seed.
99    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
100    pub name: Option<String>,
101}
102
103impl Segment {
104    /// Creates a new [`Segment`] from a [`Element`] which starts/ends
105    /// according to `timing`.
106    pub fn new(composition_type: impl Element, timing: impl Into<Timing>) -> Segment {
107        Segment {
108            element: Box::new(composition_type),
109            timing: timing.into(),
110            name: Option::default(),
111        }
112    }
113
114    /// Gives this [`Segment`] a name, used to seed its [`Rng`](rand::Rng), and returns the new named version. Useful if
115    /// you want certain segments to be repeated/reproduced (i.e. be rendered with the same Rng).
116    pub fn named(mut self, name: String) -> Self {
117        self.name = Some(name);
118
119        self
120    }
121
122    /// Removes the [`Segment`]'s a name, if it has one, returning the resulting unnamed segment.
123    pub fn unnamed(mut self) -> Self {
124        self.name = None;
125
126        self
127    }
128
129    /// Gets the contained element if its type matches type `Element`, otherwise, `None` is
130    /// returned.
131    pub fn element_as<Element: crate::Element>(&self) -> Option<&Element> {
132        successors(Some(&*self.element), |s| s.wrapped_element())
133            .find_map(|s| s.as_any().downcast_ref::<Element>())
134    }
135}
136
137impl RangeBounds<i32> for Segment {
138    fn start_bound(&self) -> Bound<&i32> {
139        self.timing.start_bound()
140    }
141
142    fn end_bound(&self) -> Bound<&i32> {
143        self.timing.end_bound()
144    }
145}
146
147impl RangeBounds<i32> for &Segment {
148    fn start_bound(&self) -> Bound<&i32> {
149        self.timing.start_bound()
150    }
151
152    fn end_bound(&self) -> Bound<&i32> {
153        self.timing.end_bound()
154    }
155}
156
157/// A typed view of a [`Segment`] (references to its fields).
158#[derive(Debug)]
159pub struct SegmentRef<'a, T: Element> {
160    /// The element reference.
161    pub element: &'a T,
162    /// The segment's timing reference.
163    pub timing: &'a Timing,
164    /// The segment's name reference.
165    pub name: &'a Option<String>,
166}
167
168impl<'a, T: Element> Clone for SegmentRef<'a, T> {
169    fn clone(&self) -> Self {
170        *self
171    }
172}
173
174impl<'a, T: Element> Copy for SegmentRef<'a, T> {}
175
176impl<'a, T: Element> TryFrom<&'a Segment> for SegmentRef<'a, T> {
177    type Error = ConversionError;
178
179    fn try_from(value: &'a Segment) -> std::result::Result<Self, Self::Error> {
180        if let Some(casted_ref) = value.element_as::<T>() {
181            Ok(SegmentRef {
182                element: casted_ref,
183                timing: &value.timing,
184                name: &value.name,
185            })
186        } else {
187            Err(ConversionError::TypeMismatch)
188        }
189    }
190}
191
192impl<'a, T> IntoSegment for SegmentRef<'a, T>
193where
194    T: Element + Clone,
195{
196    /// Turns this [`SegmentRef`] into a new [`Segment`] with a given
197    /// `timing`.
198    ///
199    /// Note: This also copies the `name` if it exists. If this is not desired, use:
200    /// ```
201    /// # use redact_composer_core::elements::PlayNote;
202    /// # use redact_composer_core::SegmentRef;
203    /// # use redact_composer_core::timing::Timing;
204    /// # use redact_composer_core::IntoSegment;
205    /// # let timing = Timing::from(0..1);
206    /// # let s = (PlayNote { note: 0, velocity: 0}, Timing::from(0..1), None);
207    /// # let segment_ref = SegmentRef { element: &s.0,timing: &s.1, name: &s.2 };
208    /// let segment = segment_ref.into_segment(timing).unnamed();
209    /// ```
210    fn into_segment(self, timing: impl Into<Timing>) -> Segment {
211        if let Some(name) = self.name {
212            self.element
213                .clone()
214                .into_segment(timing)
215                .named(name.clone())
216        } else {
217            self.element.clone().into_segment(timing)
218        }
219    }
220
221    fn over(self, timing: impl Into<Timing>) -> Segment {
222        self.into_segment(timing)
223    }
224}
225
226impl<'a, T: Element> RangeBounds<i32> for SegmentRef<'a, T> {
227    fn start_bound(&self) -> Bound<&i32> {
228        self.timing.start_bound()
229    }
230
231    fn end_bound(&self) -> Bound<&i32> {
232        self.timing.end_bound()
233    }
234}
235
236impl<'a, T: Element> From<SegmentRef<'a, T>> for Timing {
237    fn from(value: SegmentRef<'a, T>) -> Self {
238        *value.timing
239    }
240}
241
242impl<'a, T: Element> From<&SegmentRef<'a, T>> for Timing {
243    fn from(value: &SegmentRef<'a, T>) -> Self {
244        *value.timing
245    }
246}
247
248impl<'a, T: Element> From<SegmentRef<'a, T>> for Range<i32> {
249    fn from(value: SegmentRef<'a, T>) -> Self {
250        value.timing.into()
251    }
252}
253
254impl<'a, T: Element> From<&SegmentRef<'a, T>> for Range<i32> {
255    fn from(value: &SegmentRef<'a, T>) -> Self {
256        value.timing.into()
257    }
258}
259
260/// Conversion methods to create a [`Segment`] from a [`Element`].
261pub trait IntoSegment: private::Sealed {
262    /// Creates a [`Segment`] from this element, spanning the given time range.
263    fn into_segment(self, timing: impl Into<Timing>) -> Segment;
264
265    /// Creates a [`Segment`] from this element, spanning the given time range.
266    fn over(self, timing: impl Into<Timing>) -> Segment;
267}
268
269impl<T: Element> IntoSegment for T {
270    /// Creates a [`Segment`] from this element, spanning the given time range.
271    fn into_segment(self, timing: impl Into<Timing>) -> Segment {
272        Segment::new(self, timing)
273    }
274
275    /// Creates a [`Segment`] from this element, spanning the given time range.
276    fn over(self, timing: impl Into<Timing>) -> Segment {
277        self.into_segment(timing)
278    }
279}
280
281/// Core types implementing [`Element`].
282pub mod elements {
283    use super::PartType;
284    use crate::derive::Element;
285    use crate::Element;
286
287    #[cfg(feature = "serde")]
288    use serde::{Deserialize, Serialize};
289
290    /// Play a note with a velocity.
291    #[derive(Element, Clone, Copy, Debug, Eq, PartialEq)]
292    #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
293    pub struct PlayNote {
294        /// Note represented as u8, with `note % 12 == 0` representing 'C'.
295        pub note: u8,
296        /// The strength of attack of the note.
297        pub velocity: u8,
298    }
299
300    /// Wraps another element, indicating that notes rendered from the wrapped element are to be
301    /// played by a single instrument at a time.
302    #[derive(Element, Debug)]
303    #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
304    #[element(wrapped_element = self.wrapped_element())]
305    pub struct Part(pub(super) Box<dyn Element>, pub(super) PartType);
306}
307use elements::Part;
308use log::{debug, info, log_enabled, trace, warn, Level};
309
310/// Indicates whether a part is an instrument, or percussion.
311#[derive(Debug, Clone, Copy)]
312#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
313pub enum PartType {
314    /// Instrument part.
315    Instrument,
316    /// Percussion part.
317    Percussion,
318}
319
320impl Part {
321    /// Creates a new instrument part from the given element.
322    pub fn instrument(wrapped_element: impl Element) -> crate::elements::Part {
323        Part(Box::new(wrapped_element), PartType::Instrument)
324    }
325
326    /// Creates a new percussion part from the given element.
327    pub fn percussion(wrapped_element: impl Element) -> crate::elements::Part {
328        Part(Box::new(wrapped_element), PartType::Percussion)
329    }
330
331    /// Returns the wrapped element.
332    pub fn wrapped_element(&self) -> Option<&dyn Element> {
333        Some(&*self.0)
334    }
335
336    /// Returns the type of this part.
337    pub fn part_type(&self) -> &PartType {
338        &self.1
339    }
340}
341
342/// Options used by a [`Composer`].
343#[derive(Debug, Copy, Clone, Eq, PartialEq)]
344#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
345pub struct ComposerOptions {
346    /// The number of ticks per beat.
347    pub ticks_per_beat: i32,
348}
349
350impl Default for ComposerOptions {
351    fn default() -> Self {
352        Self {
353            ticks_per_beat: STANDARD_BEAT_LENGTH,
354        }
355    }
356}
357
358/// Provides methods to create compositions using a [`RenderEngine`] and its
359/// [`Renderer`](render::Renderer)s.
360#[derive(Debug, Default)]
361pub struct Composer {
362    /// The render engine used when rendering compositions.
363    pub engine: RenderEngine,
364    /// The composer's options.
365    pub options: ComposerOptions,
366}
367
368impl From<RenderEngine> for Composer {
369    fn from(value: RenderEngine) -> Self {
370        Composer {
371            engine: value,
372            ..Default::default()
373        }
374    }
375}
376
377/// Options used during the rendering of a [`Composition`].
378#[derive(Debug, Copy, Clone, Eq, PartialEq)]
379#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
380pub struct CompositionOptions {
381    /// The number of ticks per beat.
382    pub ticks_per_beat: i32,
383}
384
385impl Default for CompositionOptions {
386    fn default() -> Self {
387        Self {
388            ticks_per_beat: STANDARD_BEAT_LENGTH,
389        }
390    }
391}
392
393impl From<ComposerOptions> for CompositionOptions {
394    fn from(value: ComposerOptions) -> Self {
395        Self {
396            ticks_per_beat: value.ticks_per_beat,
397        }
398    }
399}
400
401#[derive(Debug)]
402#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
403/// A composition output, including the tree of rendered segments, produced from
404/// [`Composer::compose`].
405pub struct Composition {
406    /// The options used during this composition.
407    pub options: CompositionOptions,
408    /// The tree of rendered [`Segment`]s produced during composition.
409    pub tree: Tree<RenderSegment>,
410}
411
412impl Composer {
413    /// Generates a [`Composition`] from a starting [Segment].
414    pub fn compose(&self, seg: Segment) -> Composition {
415        let mut hasher = XxHash64::with_seed(0);
416        thread_rng().next_u64().hash(&mut hasher);
417        self.compose_with_seed(seg, hasher.finish())
418    }
419    /// Generates a [`Composition`] from a starting [Segment], using a seed to to
420    /// create a reproducible output.
421    pub fn compose_with_seed(&self, seg: Segment, seed: u64) -> Composition {
422        info!(target: LOG, "Composing {:?} with seed {:?}.", seg, seed);
423        debug!(target: LOG, "{:?}", self.options);
424        let start_time = std::time::Instant::now();
425        let options: CompositionOptions = self.options.into();
426        let mut render_tree = Tree::new();
427        let mut type_cache: Vec<HashSet<TypeId>> = Vec::new();
428        let node_id = render_tree.insert(
429            RenderSegment {
430                rendered: false,
431                seed,
432                segment: seg,
433                error: None,
434            },
435            None,
436        );
437        type_cache.insert(node_id, HashSet::default());
438
439        // Nodes are rendered in depth-first order, meaning any children of a node will be rendered
440        // before its siblings (assuming their required context is available). Nodes which cannot be
441        // rendered (due to missing context) are skipped until their context dependencies are met.
442        //
443        // `render_stack` keeps track the (reverse) sequence of node ids to render, enabling this
444        // depth-first ordering without having to do any element shifting.
445        let mut render_stack = vec![0];
446        loop {
447            let mut added_node_count = 0;
448
449            for render_stack_idx in (0_usize..render_stack.len()).rev() {
450                let node_idx = render_stack[render_stack_idx];
451                let is_top_of_render_stack = render_stack_idx + 1 == render_stack.len();
452
453                // Already rendered nodes can be skipped (and removed if at the top of the render stack).
454                if render_tree[node_idx].value.rendered {
455                    if is_top_of_render_stack {
456                        render_stack.pop();
457                    }
458                    continue;
459                }
460
461                let composition_context = CompositionContext::new(
462                    &options,
463                    &render_tree,
464                    &render_tree[node_idx],
465                    Some(&type_cache),
466                );
467
468                trace!(target: LOG, "Rendering: {:?}", &render_tree[node_idx]);
469                let result = self
470                    .engine
471                    .render(&render_tree[node_idx].value.segment, composition_context);
472
473                if let Some(render_res) = result {
474                    match render_res {
475                        // Case: Unable to render -- most commonly missing required context
476                        // Later iterations will retry
477                        crate::render::Result::Err(err) => {
478                            trace!(target: LOG, "Rendering (Node idx: {:?}) was unsuccessful: {:?}",
479                                &render_tree[node_idx].idx, err);
480                            render_tree[node_idx].value.error = Some(err);
481                        }
482                        // Case: Successfully rendered
483                        crate::render::Result::Ok(segments) => {
484                            trace!(target: LOG, "Rendering (Node idx: {:?}) succeeded, producing \
485                            {:?} children.", &render_tree[node_idx].idx, segments.len());
486
487                            // Create an Rng used to generate seeds for rendered children
488                            let mut hasher = XxHash64::default();
489                            render_tree[node_idx].value.seed.hash(&mut hasher);
490                            let mut rng = ChaCha12Rng::seed_from_u64(hasher.finish());
491
492                            let children: Vec<RenderSegment> = segments
493                                .into_iter()
494                                .map(|s| RenderSegment {
495                                    rendered: !self.engine.can_render(&*s.element),
496                                    seed: match &s.name {
497                                        None => {
498                                            let mut hasher = XxHash64::default();
499                                            rng.next_u64().hash(&mut hasher);
500                                            hasher.finish()
501                                        }
502                                        Some(name) => {
503                                            let mut hasher = XxHash64::default();
504                                            render_tree[node_idx].value.seed.hash(&mut hasher);
505                                            name.hash(&mut hasher);
506                                            hasher.finish()
507                                        }
508                                    },
509                                    segment: s,
510                                    error: None,
511                                })
512                                .collect();
513
514                            added_node_count += children.len();
515                            let mut added_node_ids = vec![];
516
517                            for child in children {
518                                // Update the type cache (map of nodes and which other types of nodes they contain)
519                                let type_ids = successors(Some(&*child.segment.element), |s| {
520                                    s.wrapped_element()
521                                })
522                                .map(|s| s.as_any().type_id())
523                                .collect::<HashSet<_>>();
524                                for ancestor_idx in
525                                    successors(Some(node_idx), |p_idx| render_tree[*p_idx].parent)
526                                        .collect::<Vec<_>>()
527                                {
528                                    type_cache[ancestor_idx].extend(type_ids.iter().copied());
529                                }
530
531                                let node_id = render_tree.insert(child, Some(node_idx));
532                                type_cache.insert(node_id, HashSet::default());
533                                added_node_ids.push(node_id);
534                            }
535
536                            render_tree[node_idx].value.rendered = true;
537                            render_tree[node_idx].value.error = None;
538
539                            // Nodes are only rendered once so it can be removed if at the top of the stack.
540                            // If not at the top, it will be removed at a later iteration (preventing
541                            // unnecessary element shifting).
542                            if is_top_of_render_stack {
543                                render_stack.pop();
544                            }
545                            // Add the new node ids to the top of the render stack in reverse order
546                            // (reverse order ensures they are rendered in the same order they were produced)
547                            render_stack
548                                .append(&mut added_node_ids.into_iter().rev().collect::<Vec<_>>());
549
550                            // Breaking here ensures depth-first rendering by starting the iteration over
551                            // from the top of the render_stack (which is where the newly added nodes are).
552                            if added_node_count > 0 {
553                                break;
554                            }
555                        }
556                    }
557                }
558            }
559
560            // If no nodes were added, no further progress can be made -- rendering complete.
561            if added_node_count == 0 {
562                break;
563            }
564        }
565
566        let duration = std::time::Instant::now().duration_since(start_time);
567        info!(target: LOG, "Finished composing. ({:?})", duration);
568
569        if log_enabled!(target: LOG, Level::Warn) {
570            render_tree
571                .iter()
572                .filter(|n| !n.value.rendered)
573                .for_each(|n| warn!(target: LOG, "Unrendered: {:?}", n));
574        }
575
576        Composition {
577            options: self.options.into(),
578            tree: render_tree,
579        }
580    }
581}
582
583mod private {
584    use crate::SegmentRef;
585
586    pub trait Sealed {}
587
588    impl<T: super::Element> Sealed for T {}
589    impl<T: super::Element> Sealed for SegmentRef<'_, T> {}
590}