1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
//! The [`Graph`](./struct.Graph.html) type constructs a directed, acyclic graph of DSP `Node`
//! types.
//!
//! It supports multiple input and multiple output nodes per node.
//!
//! `Graph` uses the daggy crate. See more [here](https://crates.io/crates/daggy).
//!
//! The `Graph` type requires that its nodes implement the [`Node`](../node/trait.Node.html) trait.

use daggy::{self, Walker};
use node::Node;
use sample::{self, Frame, Sample};


/// An alias for our Graph's Node Index.
pub type NodeIndex = daggy::NodeIndex<usize>;
/// An alias for our Graph's Edge Index.
pub type EdgeIndex = daggy::EdgeIndex<usize>;

/// An alias for the iterator yielding mutable access to all node weights.
pub type NodesMut<'a, N> = daggy::NodeWeightsMut<'a, N, usize>;

/// Read only access to a **Graph**'s internal node array.
pub type RawNodes<'a, N> = daggy::RawNodes<'a, N, usize>;
/// Read only access to a **Graph**'s internal edge array.
pub type RawEdges<'a, F> = daggy::RawEdges<'a, Connection<F>, usize>;

/// An iterator yielding indices to recently added connections.
pub type EdgeIndices = daggy::EdgeIndices<usize>;

/// An alias for the **Dag** used within our **Graph**.
pub type Dag<F, N> = daggy::Dag<N, Connection<F>, usize>;

/// An alias for the **PetGraph** used by our **Graph**'s internal **Dag**.
pub type PetGraph<F, N> = daggy::PetGraph<N, Connection<F>, usize>;

/// A directed, acyclic DSP graph.
///
/// Designed for easily and safely setting up high performance audio signal generating, processing
/// and mixing. Useful for both simple and highly complex signal graphs.
///
/// There are a variety of use cases for `Graph`:
///
/// - Designing effects.
/// - Creating an audio mixer.
/// - Making a sampler.
/// - Writing a DSP backend for a DAW.
/// - Any kind of modular audio synthesis or processing.
///
/// `Graph` is a wrapper around [daggy](http://mitchmindtree.github.io/daggy/daggy/)'s
/// [`Dag`](http://mitchmindtree.github.io/daggy/daggy/struct.Dag.html) type - an abstraction for
/// working with directed acyclic graph's where high performance node adding and accessing is
/// required.
///
/// An input -> output connection in this `Graph` is represented as a parent -> child connection
/// within the internal `Dag`. The following terms are all equivalent:
///
/// - *input -> output*
/// - *src -> dest*
/// - *parent -> child*
///
/// Audio can be requested from any node in the **Graph** using the
/// [`audio_requested_from`](./struct.Graph.html#method.audio_requested_from) method.
///
/// When [`audio_requested`](../node/trait.Node.html#method.audio_requested) is called on the
/// **Graph**, audio will be requested from the node specified by the index at `maybe_master`. If
/// `maybe_master` is `None`, audio will be requested from the first, input-only node found - that
/// is, the first node that is found with only input connections and no outputs.
///
/// **NodeIndex** is a type that acts as a reference to a node, while **EdgeIndex** is a type that
/// acts as a reference to an edge (which in this case describes a *src -> dest* **Connection**
/// between two nodes). It should be noted that these are only stable across certain operations.
/// **Removing indices may shift other indices of the same type!** Adding nodes or edges to the
/// **Graph** keeps all indices stable, but removing a node or edge will force the last node/edge
/// to shift its index to take its place.
///
/// **Graph** also offers methods for accessing its underlying **Dag** or **PetGraph**.
#[derive(Clone, Debug)]
pub struct Graph<F, N> {
    dag: Dag<F, N>,
    /// The order in which audio will be requested from each node.
    visit_order: Vec<NodeIndex>,
    /// The node from which audio will be requested upon a call to `Node::audio_requested`.
    maybe_master: Option<NodeIndex>,
    /// A buffer to re-use when mixing the dry and wet signals when audio is requested.
    dry_buffer: Vec<F>,
}

/// Describes a connection between two Nodes within the Graph: *input -> connection -> output*.
///
/// **Graph**'s API only allows for read-only access to **Connection**s, so you can be sure that
/// their buffers always represent the last frames rendered by their input node.
#[derive(Clone, Debug)]
pub struct Connection<F> {
    /// The buffer used to pass audio between nodes.
    ///
    /// After `Graph::audio_requested_from` is called, this buffer will contain the audio rendered
    /// by the **Connection**'s input node.
    pub buffer: Vec<F>,
}

/// The error returned when adding an edge that would create a cycle.
#[derive(Copy, Clone, Debug)]
pub struct WouldCycle;

/// A walker object for walking over nodes that are inputs to some node.
pub struct Inputs<F, N> {
    parents: daggy::Parents<N, Connection<F>, usize>,
}

/// A walker object for walking over nodes that are outputs to some node.
pub struct Outputs<F, N> {
    children: daggy::Children<N, Connection<F>, usize>,
}

/// A walker type for walking over a **Graph**'s nodes in the order in which they will visited when
/// audio is requested from the **Graph**.
pub struct VisitOrder {
    current_visit_order_idx: usize,
}

/// A walker type for walking over a **Graph**'s nodes in the order in which they will visited when
/// audio is requested from the **Graph**.
pub struct VisitOrderReverse {
    current_visit_order_idx: usize,
}


impl<F, N> Graph<F, N>
    where F: Frame, N: Node<F>
{

    /// Constructor for a new dsp Graph.
    ///
    /// [`with_capacity`](./struct.Graph.html#method.with_capacity) is recommended if you have a
    /// rough idea of the number of nodes, connections and frames per buffer upon the **Graph**'s
    /// instantiation.
    pub fn new() -> Self {
        let dag = daggy::Dag::new();
        Graph {
            dag: dag,
            visit_order: Vec::new(),
            dry_buffer: Vec::new(),
            maybe_master: None,
        }
    }

    /// Constructor for a new dsp Graph with some minimum capacity.
    ///
    /// - **nodes** is the capacity for the underlying **Dag**'s node `Vec`.
    /// - **connections** is the capacity for the underlying **Dag**'s edge `Vec`.
    /// - **frames_per_buffer** is the capacity for the **Graph**'s `dry_buffer`, which is used
    /// for mixing the dry and wet signals when `Node::audio_requested` is called.
    pub fn with_capacity(nodes: usize, connections: usize, frames_per_buffer: usize) -> Self {
        Graph {
            dag: daggy::Dag::with_capacity(nodes, connections),
            visit_order: Vec::with_capacity(nodes),
            dry_buffer: Vec::with_capacity(frames_per_buffer),
            maybe_master: None,
        }
    }

    /// A reference to the underlying **Dag**.
    pub fn dag(&self) -> &Dag<F, N> {
        &self.dag
    }

    /// Takes ownership of the **Graph** and returns the underlying **Dag**.
    pub fn into_dag(self) -> Dag<F, N> {
        let Graph { dag, .. } = self;
        dag
    }

    /// A reference to the internal **Dag**'s underlying **PetGraph**.
    pub fn pet_graph(&self) -> &PetGraph<F, N> {
        self.dag.graph()
    }

    /// Takes ownership of the **Graph** and returns the internal **Dag**'s underlying **PetGraph**.
    pub fn into_pet_graph(self) -> PetGraph<F, N> {
        self.into_dag().into_graph()
    }

    /// The total number of nodes in the **Graph**.
    pub fn node_count(&self) -> usize {
        self.dag.node_count()
    }

    /// The total number of connections in the **Graph**.
    pub fn connection_count(&self) -> usize {
        self.dag.edge_count()
    }

    /// Return the **Graph**'s master index if there is one.
    ///
    /// **Graph**'s **Node** implementation will request audio from the node at `maybe_master`
    /// when the `Node::audio_requested` method is called.
    pub fn master_index(&self) -> Option<NodeIndex> {
        self.maybe_master
    }

    /// Set the master node for the **Graph**.
    ///
    /// **Graph** will check to see if a node exists for the given index before assigning.
    ///
    /// **Graph**'s **Node** implementation will request audio from the node at `maybe_master`
    /// when the `Node::audio_requested` method is called.
    pub fn set_master(&mut self, maybe_index: Option<NodeIndex>) {
        let maybe_index = maybe_index.and_then(|index| {
            if self.dag.node_weight(index).is_some() { Some(index) } else { None }
        });
        self.maybe_master = maybe_index;
        self.prepare_visit_order();
    }

    /// Add a node to the dsp graph.
    ///
    /// This computes in **O(1)** time.
    pub fn add_node(&mut self, node: N) -> NodeIndex {
        let idx = self.dag.add_node(node);
        idx
    }

    /// A reference to the node at the given index (or `None` if it doesn't exist).
    pub fn node(&self, node: NodeIndex) -> Option<&N> {
        self.dag.node_weight(node)
    }

    /// A mutable reference to the node at the given index (or `None` if it doesn't exist).
    pub fn node_mut(&mut self, node: NodeIndex) -> Option<&mut N> {
        self.dag.node_weight_mut(node)
    }

    /// Read only access to the internal node array.
    pub fn raw_nodes(&self) -> RawNodes<N> {
        self.dag.raw_nodes()
    }

    /// An iterator yielding mutable access to all nodes.
    /// 
    /// The order in which nodes are yielded matches the order of their indices.
    pub fn nodes_mut(&mut self) -> NodesMut<N> {
        self.dag.node_weights_mut()
    }

    /// A reference to the connection at the given index (or `None` if it doesn't exist).
    pub fn connection(&self, edge: EdgeIndex) -> Option<&Connection<F>> {
        self.dag.edge_weight(edge)
    }

    /// Read only access to the internal edge array.
    pub fn raw_edges(&self) -> RawEdges<F> {
        self.dag.raw_edges()
    }

    /// Index the **Graph** by two `NodeIndex`s at once.
    ///
    /// **Panics** if the indices are equal or if they are out of bounds.
    pub fn index_twice_mut(&mut self, a: NodeIndex, b: NodeIndex) -> (&mut N, &mut N) {
        self.dag.index_twice_mut(a, b)
    }

    /// Remove a node from the dsp graph.
    ///
    /// Resets the master to None if the index matches the current master index.
    ///
    /// **Note:** This method may shift (and in turn invalidate) previously returned node indices!
    ///
    /// **Graph** will re-prepare its visit order if some node was removed.
    pub fn remove_node(&mut self, idx: NodeIndex) -> Option<N> {
        if self.maybe_master == Some(idx) {
            self.maybe_master = None;
        }
        self.dag.remove_node(idx).map(|node| {
            self.prepare_visit_order();
            node
        })
    }

    /// Adds an edge from `src` to `dest`. That is, `src` is now an input to `dest`.
    ///
    /// Returns an error instead if the input would create a cycle in the graph.
    ///
    /// **Graph** will re-prepare its visit order if some connection was successfully added.
    ///
    /// If you're using `add_node` followed by this method, consider using
    /// [`add_input`](./struct.Graph.html#method.add_input) or
    /// [`add_output`](./struct.Graph.html#method.add_output) instead for greater performance.
    /// This is because when adding a new node and edge simultaneously, we don't have to check
    /// whether adding the edge would create a cycle.
    ///
    /// **Panics** if there is no node for either `src` or `dest`.
    ///
    /// **Panics** if the Graph is at the maximum number of edges for its index.
    pub fn add_connection(&mut self, src: NodeIndex, dest: NodeIndex)
        -> Result<EdgeIndex, WouldCycle>
    {
        self.dag.add_edge(src, dest, Connection { buffer: Vec::new() })
            .map(|edge| { self.prepare_visit_order(); edge })
            .map_err(|_| WouldCycle)
    }

    /// The same as [`add_connection`](./struct.Graph.html#method.add_connection) but adds
    /// multiple connections to the **Graph**. Rather than checking for introduced cycles and
    /// re-preparing the visit order after adding each edge, we only do so after **all** edges are
    /// added. Thus, this is a far more efficient alternative to repeatedly calling the
    /// `add_connection` method.
    ///
    /// Returns an error instead if any of the connections would create a cycle in the graph.
    ///
    /// **Graph** will re-prepare its visit order if the connections were successfully added.
    ///
    /// If you're using `add_node` followed by this method, consider using
    /// [`add_input`](./struct.Graph.html#method.add_input) or
    /// [`add_output`](./struct.Graph.html#method.add_output) instead for greater performance.
    /// This is because when adding a new node and edge simultaneously, we don't have to check
    /// whether adding the edge would create a cycle.
    ///
    /// **Panics** if there is no node for either `src` or `dest`.
    ///
    /// **Panics** if the Graph is at the maximum number of edges for its index.
    pub fn add_connections<I>(&mut self, connections: I) -> Result<EdgeIndices, WouldCycle> where
        I: ::std::iter::IntoIterator<Item=(NodeIndex, NodeIndex)>,
    {
        fn new_connection<F>() -> Connection<F> { Connection { buffer: Vec::new() } }
        self.dag.add_edges(connections.into_iter().map(|(src, dest)| (src, dest, new_connection())))
            .map(|edges| { self.prepare_visit_order(); edges })
            .map_err(|_| WouldCycle)
    }

    /// Find and return the index to the edge that describes the connection where `src` is an input
    /// to `dest`.
    ///
    /// Computes in **O(e')** time, where **e'** is the number of edges connected to the nodes `a`
    /// and `b`.
    pub fn find_connection(&self, src: NodeIndex, dest: NodeIndex) -> Option<EdgeIndex> {
        self.dag.find_edge(src, dest)
    }

    /// Remove the connection described by the edge at the given index.
    ///
    /// Returns true if an edge was removed, returns false if there was no edge at the given index.
    ///
    /// Re-prepares the visit order if some edge was removed.
    pub fn remove_edge(&mut self, edge: EdgeIndex) -> bool {
        if self.dag.remove_edge(edge).is_some() {
            self.prepare_visit_order();
            true
        } else {
            false
        }
    }

    /// Find and remove any connection between a and b if there is one, whether it is *a -> b* or
    /// *b -> a*. We know that their may only be one edge as our API does not allow for creating a
    /// cyclic graph.
    ///
    /// Returns true if an edge was removed, returns false if there was no edge at the given index.
    ///
    /// Graph will re-prepare its visit order if some edge was removed.
    ///
    /// Note: If you have an index to the edge you want to remove,
    /// [`remove_edge`](./struct.Graph.html#method.remove_edge) is a more performant option.
    pub fn remove_connection(&mut self, a: NodeIndex, b: NodeIndex) -> bool {
        match self.dag.find_edge(a, b).or_else(|| self.dag.find_edge(b, a)) {
            Some(edge) => self.remove_edge(edge),
            None => false,
        }
    }

    /// Add a new node weight to the graph as an input to the wait at the given `dest` node index.
    ///
    /// *src -> new edge -> dest*
    ///
    /// Returns an index to both the new `src` node and the edge that represents the new connection
    /// between it and the node at `dest`.
    ///
    /// Computes in **O(n)** time where n is the number of nodes. This is because must update the
    /// visit order after adding the new connection.
    ///
    /// **Panics** if there is no node for the given `dest` index.
    ///
    /// **Panics** if the Graph is at the maximum number of edges for its index.
    pub fn add_input(&mut self, src: N, dest: NodeIndex) -> (EdgeIndex, NodeIndex) {
        let indices = self.dag.add_parent(dest, Connection { buffer: Vec::new() }, src);
        self.prepare_visit_order();
        indices
    }

    /// Add a new node weight to the graph as an output to the wait at the given `src` node index.
    ///
    /// *src -> new edge -> dest*
    ///
    /// Returns an index to both the new `dest` node and the edge that represents the new connection
    /// between it and the node at `src`.
    ///
    /// Computes in **O(n)** time where n is the number of nodes. This is because must update the
    /// visit order after adding the new connection.
    ///
    /// **Panics** if there is no node for the given `dest` index.
    ///
    /// **Panics** if the Graph is at the maximum number of edges for its index.
    pub fn add_output(&mut self, src: NodeIndex, dest: N) -> (EdgeIndex, NodeIndex) {
        let indices = self.dag.add_child(src, Connection { buffer: Vec::new() }, dest);
        self.prepare_visit_order();
        indices
    }

    /// A "walker" object that may be used to step through the inputs of the given node.
    ///
    /// Unlike the `Inputs` type, `WalkInputs` does not borrow the `Graph`.
    ///
    /// Can be converted to an iterator using `.iter()`.
    pub fn inputs(&self, idx: NodeIndex) -> Inputs<F, N> {
        Inputs { parents: self.dag.parents(idx) }
    }

    /// A "walker" object that may be used to step through the outputs of the given node.
    ///
    /// Unlike the `Outputs` type, `WalkOutputs` does not borrow the **Graph**.
    ///
    /// Can be converted to an iterator using `.iter()`.
    pub fn outputs(&self, idx: NodeIndex) -> Outputs<F, N> {
        Outputs { children: self.dag.children(idx) }
    }

    /// A "walker" type that may be used to step through all node indices in the order in which
    /// they will be visited when audio is requested from the **Graph**.
    pub fn visit_order(&self) -> VisitOrder {
        VisitOrder { current_visit_order_idx: 0 }
    }

    /// A "walker" type that may be used to step through all node indices in the order in which
    /// they will be visited when audio is requested from the **Graph**.
    ///
    /// Unlike the VisitOrder type, VisitOrder does not borrow the **Graph**.
    pub fn visit_order_rev(&self) -> VisitOrderReverse {
        VisitOrderReverse { current_visit_order_idx: self.visit_order.len() }
    }

    /// Remove all incoming connections to the node at the given index.
    ///
    /// Return the number of connections removed.
    pub fn remove_all_input_connections(&mut self, idx: NodeIndex) -> usize {
        let mut inputs = self.inputs(idx);
        let mut num = 0;
        while let Some(connection) = inputs.next_edge(&self) {
            self.remove_edge(connection);
            num += 1;
        }
        num
    }

    /// Remove all outgoing connections from the node at the given index.
    ///
    /// Return the number of connections removed.
    pub fn remove_all_output_connections(&mut self, idx: NodeIndex) -> usize {
        let mut outputs = self.outputs(idx);
        let mut num = 0;
        while let Some(connection) = outputs.next_edge(&self) {
            self.remove_edge(connection);
            num += 1;
        }
        num
    }

    /// Clear all dsp nodes that have no inputs or outputs.
    ///
    /// Returns the number of nodes removed.
    ///
    /// Note: this may shift (and in turn invalidate) previously returned node and edge indices!
    pub fn clear_disconnected(&mut self) -> usize {
        let mut num_removed = 0;
        for i in 0..self.dag.node_count() {
            let idx = NodeIndex::new(i);
            let num_inputs = self.inputs(idx).count(self);
            let num_outputs = self.outputs(idx).count(self);
            if num_inputs == 0 && num_outputs == 0 {
                if self.maybe_master == Some(idx) {
                    self.maybe_master = None;
                }
                self.dag.remove_node(idx);
                num_removed += 1;
            }
        }
        num_removed
    }

    /// Clear all dsp nodes.
    pub fn clear(&mut self) {
        self.dag.clear();
        self.visit_order.clear();
        self.maybe_master = None;
    }

    /// Prepare the buffers for all nodes within the Graph.
    pub fn prepare_buffers(&mut self, buffer_size: usize) {

        // Initialise the dry signal buffer.
        resize_buffer_to(&mut self.dry_buffer, buffer_size);

        // Initialise all connection buffers.
        for connection in self.dag.edge_weights_mut() {
            resize_buffer_to(&mut connection.buffer, buffer_size);
        }
    }

    /// Request audio from the node at the given index.
    ///
    /// **Panics** if there is no node for the given index.
    pub fn audio_requested_from(&mut self, out_node: NodeIndex, output: &mut [F], sample_hz: f64) {
        // We can only go on if a node actually exists for the given index.
        if self.node(out_node).is_none() {
            panic!("No node for the given index");
        }

        let buffer_size = output.len();

        // Ensure the dry_buffer is the same length as the output buffer.
        if self.dry_buffer.len() != buffer_size {
            resize_buffer_to(&mut self.dry_buffer, buffer_size);
        }

        let mut visit_order = self.visit_order();
        while let Some(node_idx) =  visit_order.next(self) {

            // Set the buffers to equilibrium, ready to sum the inputs of the current node.
            for i in 0..buffer_size {
                output[i] = F::equilibrium();
                self.dry_buffer[i] = F::equilibrium();
            }

            // Walk over each of the input connections to sum their buffers to the output.
            let mut inputs = self.inputs(node_idx);
            while let Some(connection_idx) = inputs.next_edge(self) {
                let connection = &self[connection_idx];
                // Sum the connection's buffer onto the output.
                //
                // We can be certain that `connection`'s buffer is the same size as the
                // `output` buffer as all connections are visited from their input nodes
                // (towards the end of the visit_order while loop) before being visited here
                // by their output nodes.
                sample::slice::zip_map_in_place(output, &connection.buffer, |out_frame, con_frame| {
                    out_frame.zip_map(con_frame, |out_sample, con_sample| {
                        let out_signed = out_sample.to_sample::<<F::Sample as Sample>::Signed>();
                        let con_signed = con_sample.to_sample::<<F::Sample as Sample>::Signed>();
                        (out_signed + con_signed).to_sample::<F::Sample>()
                    })
                });
            }

            // Store the dry signal in the dry buffer for later summing.
            sample::slice::write(&mut self.dry_buffer, output);

            // Render the audio with the current node and sum the dry and wet signals.
            let (dry, wet) = {
                let node = &mut self[node_idx];

                // Render our `output` buffer with the current node.
                // The `output` buffer is now representative of a fully wet signal.
                node.audio_requested(output, sample_hz);

                let dry = node.dry();
                let wet = node.wet();
                (dry, wet)
            };

            // Combine the dry and wet signals.
            sample::slice::zip_map_in_place(output, &self.dry_buffer,
                |f_wet, f_dry| f_wet.zip_map(f_dry, |s_wet, s_dry| {
                    let wet = s_wet.mul_amp(wet);
                    let dry = s_dry.mul_amp(dry);
                    wet.add_amp(dry.to_sample())
                })
            );

            // If we've reached our output node, we're done!
            if node_idx == out_node {
                return;
            }

            // Walk over each of the outgoing connections and write the rendered output to them.
            let mut outputs = self.outputs(node_idx);
            while let Some(connection_idx) = outputs.next_edge(self) {
                let connection = &mut self.dag[connection_idx];

                // Ensure the buffer matches the target length.
                if connection.buffer.len() != output.len() {
                    resize_buffer_to(&mut connection.buffer, output.len());
                }

                // Write the rendered audio to the outgoing connection buffers.
                sample::slice::write(&mut connection.buffer, output);
            }
        }

    }

    /// Prepare the visit order for the graph in its current state.
    ///
    /// This is called whenever the **Graph** is mutated in some way that may change the flow of
    /// its edges.
    ///
    /// When audio is requested from the graph, we need to iterate through all nodes so that all
    /// child nodes are visited before their parents. To do this, we can use petgraph's toposort
    /// algorithm to return the topological order of our graph.
    ///
    /// The user should never have to worry about this, thus the method is private.
    fn prepare_visit_order(&mut self) {
        self.visit_order = daggy::petgraph::algo::toposort(self.dag.graph());
    }

}


impl<F, N> ::std::ops::Index<NodeIndex> for Graph<F, N> {
    type Output = N;
    #[inline]
    fn index<'a>(&'a self, index: NodeIndex) -> &'a N {
        &self.dag[index]
    }
}

impl<F, N> ::std::ops::IndexMut<NodeIndex> for Graph<F, N> {
    #[inline]
    fn index_mut(&mut self, index: NodeIndex) -> &mut N {
        &mut self.dag[index]
    }
}

impl<F, N> ::std::ops::Index<EdgeIndex> for Graph<F, N> {
    type Output = Connection<F>;
    #[inline]
    fn index<'a>(&'a self, index: EdgeIndex) -> &'a Connection<F> {
        &self.dag[index]
    }
}


impl<F, N> Node<F> for Graph<F, N> where
    F: Frame,
    N: Node<F>,
{
    fn audio_requested(&mut self, output: &mut [F], sample_hz: f64) {
        match self.maybe_master {
            Some(master) => self.audio_requested_from(master, output, sample_hz),
            None => {
                // If there is no set master node, we'll start from the back of the visit_order and
                // use the first node that has no output connections.
                let mut visit_order_rev = self.visit_order_rev();
                while let Some(node) = visit_order_rev.next(self) {
                    if self.inputs(node).count(self) == 0 {
                        self.audio_requested_from(node, output, sample_hz);
                        return;
                    }
                }
            },
        }
    }
}


impl<F, N> Walker<Graph<F, N>> for Inputs<F, N> {
    type Index = usize;

    /// The next (connection, node) input pair to some node in our walk for the given **Graph**. 
    #[inline]
    fn next(&mut self, graph: &Graph<F, N>) -> Option<(EdgeIndex, NodeIndex)> {
        self.parents.next(&graph.dag)
    }

    /// The next input connection to some node in our walk for the given **Graph**.
    #[inline]
    fn next_edge(&mut self, graph: &Graph<F, N>) -> Option<EdgeIndex> {
        self.parents.next_edge(&graph.dag)
    }

    /// The next input node to some node in our walk for the given **Graph**.
    #[inline]
    fn next_node(&mut self, graph: &Graph<F, N>) -> Option<NodeIndex> {
        self.parents.next_node(&graph.dag)
    }

}


impl<F, N> Walker<Graph<F, N>> for Outputs<F, N> {
    type Index = usize;

    /// The next (connection, node) output pair from some node in our walk for the given **Graph**.
    #[inline]
    fn next(&mut self, graph: &Graph<F, N>) -> Option<(EdgeIndex, NodeIndex)> {
        self.children.next(&graph.dag)
    }

    /// The next output connection from some node in our walk for the given **Graph**.
    #[inline]
    fn next_edge(&mut self, graph: &Graph<F, N>) -> Option<EdgeIndex> {
        self.children.next_edge(&graph.dag)
    }

    /// The next output node from some node in our walk for the given **Graph**.
    #[inline]
    fn next_node(&mut self, graph: &Graph<F, N>) -> Option<NodeIndex> {
        self.children.next_node(&graph.dag)
    }

}


impl VisitOrder {
    /// The index of the next node that would be visited during audio requested in our walk of the
    /// given **Graph**'s visit order.
    #[inline]
    pub fn next<F, N>(&mut self, graph: &Graph<F, N>) -> Option<NodeIndex> {
        graph.visit_order.get(self.current_visit_order_idx).map(|&idx| {
            self.current_visit_order_idx += 1;
            idx
        })
    }
}

impl VisitOrderReverse {
    /// The index of the next node that would be visited during audio requested in our walk of the
    /// given **Graph**'s visit order.
    #[inline]
    pub fn next<F, N>(&mut self, graph: &Graph<F, N>) -> Option<NodeIndex> {
        if self.current_visit_order_idx > 0 {
            self.current_visit_order_idx -= 1;
            graph.visit_order.get(self.current_visit_order_idx).map(|&idx| idx)
        } else {
            None
        }
    }
}



/// Resize the given buffer to the given target length.
fn resize_buffer_to<F>(buffer: &mut Vec<F>, target_len: usize)
    where F: Frame,
{
    let len = buffer.len();
    if len < target_len {
        buffer.extend((len..target_len).map(|_| F::equilibrium()))
    } else if len > target_len {
        buffer.truncate(target_len);
    }
}

impl ::std::fmt::Display for WouldCycle {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
        writeln!(f, "{:?}", self)
    }
}

impl ::std::error::Error for WouldCycle {
    fn description(&self) -> &str {
        "Adding this input would have caused the graph to cycle!"
    }
}