{"action":"created","issue":{"url":"https://api.github.com/repos/RustAudio/dsp-chain/issues/49","labels_url":"https://api.github.com/repos/RustAudio/dsp-chain/issues/49/labels{/name}","comments_url":"https://api.github.com/repos/RustAudio/dsp-chain/issues/49/comments","events_url":"https://api.github.com/repos/RustAudio/dsp-chain/issues/49/events","html_url":"https://github.com/RustAudio/dsp-chain/issues/49","id":47572332,"number":49,"title":"Other user-friendly API ideas.","user":{"login":"mitchmindtree","id":4587373,"avatar_url":"https://avatars.githubusercontent.com/u/4587373?v=3","gravatar_id":"","url":"https://api.github.com/users/mitchmindtree","html_url":"https://github.com/mitchmindtree","followers_url":"https://api.github.com/users/mitchmindtree/followers","following_url":"https://api.github.com/users/mitchmindtree/following{/other_user}","gists_url":"https://api.github.com/users/mitchmindtree/gists{/gist_id}","starred_url":"https://api.github.com/users/mitchmindtree/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mitchmindtree/subscriptions","organizations_url":"https://api.github.com/users/mitchmindtree/orgs","repos_url":"https://api.github.com/users/mitchmindtree/repos","events_url":"https://api.github.com/users/mitchmindtree/events{/privacy}","received_events_url":"https://api.github.com/users/mitchmindtree/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/RustAudio/dsp-chain/labels/discussion","name":"discussion","color":"bfe5bf"},{"url":"https://api.github.com/repos/RustAudio/dsp-chain/labels/draft","name":"draft","color":"e11d21"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":3,"created_at":"2014-11-03T08:37:41Z","updated_at":"2015-03-29T05:37:58Z","closed_at":null,"body":"Currently the trait-based node graph approach is very fast, efficient, and quite user friendly. However, it has the tendency to lead toward a slightly more OOP design, which can often feel like a bit of an up-hill battle with Rust.\r\n\r\nI'm interested in coming up with some ideas for a more user-friendly, perhaps functional-esque way of describing the node graph.\r\n\r\nOne idea I was considering was to implement the bitshift operators for describing a series of inputs in a sort of `Chain`. I.e.\r\n\r\n```Rust\r\nlet chain: Chain = output << master << bus << effect << effect << synth;\r\n````\r\n\r\nwhere each element in the chain can be either\r\n- `T`\r\n- `Vec<T>` or\r\n- another `Chain`\r\n\r\nwhere T: Node.\r\n\r\nI'll keep thinking on this and try come up with some better examples."},"comment":{"url":"https://api.github.com/repos/RustAudio/dsp-chain/issues/comments/87360494","html_url":"https://github.com/RustAudio/dsp-chain/issues/49#issuecomment-87360494","issue_url":"https://api.github.com/repos/RustAudio/dsp-chain/issues/49","id":87360494,"user":{"login":"mitchmindtree","id":4587373,"avatar_url":"https://avatars.githubusercontent.com/u/4587373?v=3","gravatar_id":"","url":"https://api.github.com/users/mitchmindtree","html_url":"https://github.com/mitchmindtree","followers_url":"https://api.github.com/users/mitchmindtree/followers","following_url":"https://api.github.com/users/mitchmindtree/following{/other_user}","gists_url":"https://api.github.com/users/mitchmindtree/gists{/gist_id}","starred_url":"https://api.github.com/users/mitchmindtree/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mitchmindtree/subscriptions","organizations_url":"https://api.github.com/users/mitchmindtree/orgs","repos_url":"https://api.github.com/users/mitchmindtree/repos","events_url":"https://api.github.com/users/mitchmindtree/events{/privacy}","received_events_url":"https://api.github.com/users/mitchmindtree/received_events","type":"User","site_admin":false},"created_at":"2015-03-29T05:37:58Z","updated_at":"2015-03-29T05:37:58Z","body":"Ok, so one issue that I'm finding hard to avoid with this is approach is performance.\r\n\r\nMost DSP types will have to mutate/update some internal state (i.e. phase, ringbuffer, etc) during the audio loop. The simplest way of handling this that I've been able to come up with so far is to simply make the `Node` and `Dsp` traits' `audio_requested` method take a mutable reference to self (as is currently the case) so that a user can update the type's state at the same time audio is requested. I'm not sure it is possible to decouple these things in a way that is as performant, as for many types their mutation is dependent upon the results of their children's `audio_requested` methods.\r\n\r\nRust's bit-shift operator takes self as an immutable reference, meaning we'd have to at some point separate the immutable state from the mutable state. As mentioned above, I'm not sure if there is a solution to this that is practical, ergonomic or even possible while retaining the same performance (I'm open to ideas though).\r\n\r\nHowever, since this issue was originally posted, a [`Graph`](https://github.com/RustAudio/dsp-chain/blob/master/src/graph.rs) type has been added to the crate which behaves very similarly to the `Chain` type described above (without the fancy bit-shift operator). The `Graph` type and `Dsp` trait are designed for use together, where the `Graph` can handle any type that implements the `Dsp` trait (this includes `Graph` itself). The most special property of the `Graph` type is that it allows for multiple inputs *and* outputs (whereas the `Node` trait only allows multiple inputs), safely solving the problem of dealing with multiple mutable references and ownership.\r\n\r\nThe `Node` trait still remains, however it is unrelated to the `Graph` and `Dsp` traits and is designed for a different use case. The following two paragraphs (from the README) describe the difference between use cases for the `Graph` type and the `Node` trait.\r\n\r\n> The Node trait offers a DSP chaining design via its inputs method. It is slightly simpler to use than the Graph type however also slightly more limited. Using the Node trait, it is impossible for two nodes to reference the same input Node making it difficult to perform tasks like complex \"bussing\" and \"side-chaining\".\r\n\r\n> The Graph type constructs a directed, acyclic graph of DSP nodes. It is the recommended approach for more advanced DSP chains that involve things like \"bussing\", \"side-chaining\" or more DAW-esque behaviour. The Graph type requires its nodes to have implemented the Dsp trait (a slightly simplified version of the Node trait, though entirely unrelated). Internally, Graph uses bluss's petgraph crate.\r\n\r\nHere's the old [Node example](https://github.com/RustAudio/dsp-chain/blob/master/examples/node.rs) and here's the new [Graph example](https://github.com/RustAudio/dsp-chain/blob/master/examples/graph.rs) if you're interested.\r\n\r\nAnother area for API design that I think is definitely worth exploring is rust's awesome `Iterator` trait. For example, perhaps rather than passing a mutable buffer into an `.audio_requested` method, perhaps each `Dsp` type could return some `Iterator<Item=Sample>` that would generate a buffer worth of samples. This may offer some performance advantages by reducing the number of Vec allocations necessary... but we'd have to do some experimentation first. It's also likely that the Iterator may need to store a mutable reference to self, possibly causing some ownership issues, but i'm sure they could be dealt with safely at least within the `Graph` type. Also, in rust's current state I imagine this would be considerably trickier to implement than `audio_requested` currently is due to the difficulty of specifying Iterator return types. This would however be solved by something like [abstract/anonymous return types](https://github.com/rust-lang/rfcs/issues/518) which seems to be very high priority for post-1.0 - perhaps it is best to wait until then for further experimentation on this.\r\n\r\nFinally, I'd like to mention that the more I use Rust, the more I feel it is impractical to try and opt for either a purely OOP or a purely FP approach in terms of design. If anything, the style would probably be more accurately be described as \"Ownership Oriented Programming\" which dips into the benefits of both of the previously mentioned paradigms:\r\n- The speed of mutability in OOP\r\n- The safety and readability of FP"}}