1 // Copyright (C) 2020 Natanael Mojica <neithanmo@gmail.com>
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Library General Public
5 // License as published by the Free Software Foundation; either
6 // version 2 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Library General Public License for more details.
12 //
13 // You should have received a copy of the GNU Library General Public
14 // License along with this library; if not, write to the
15 // Free Software Foundation, Inc., 51 Franklin Street, Suite 500,
16 // Boston, MA 02110-1335, USA.
17
18 use gst::prelude::*;
19
20 use std::error::Error;
21
22 const AUDIO_SRC: &str = "audiotestsrc";
23 const AUDIO_SINK: &str = "audioconvert ! autoaudiosink";
24
25 // This example defines two instruments, the first instrument send to the output that is at its input and accumulates the received audio samples
26 // into a global variable called gasig. The execution of this instrument last the first 2 seconds.
27 // The second instrument starts it execution at 1.8 second, This instrument creates two audio buffers with samples that are read
28 // from the global accumulator(gasig), then reads these buffers at a fixed delay time, creating the adelL, adelM and adelR buffers,
29 // also, It multiplies the audio samples in the right channel by 0.5 * kdel, being kdel a line of values starting at 0.5 at increments of 0.001.
30 // Finally, those buffers are mixed with the accumulator, and an audio envelop is applied(aseg) to them.
31 // The result is similar to an audio echo in which the buffered samples are read at different delay times and also modified in frecuency(right channel),
32 // this creates an space effect using just one channel audio input.
33 const CSD: &str = "
34 <CsoundSynthesizer>
35 <CsOptions>
36 </CsOptions>
37 <CsInstruments>
38
39 sr = 44100
40 ksmps = 7
41
42 nchnls_i = 1
43 nchnls = 2
44
45 gasig init 0
46 gidel = 1
47
48 instr 1
49
50 ain in
51 outs ain, ain
52
53 vincr gasig, ain
54 endin
55
56 instr 2
57
58 ifeedback = p4
59
60 aseg linseg 1., p3, 0.0
61
62 abuf2 delayr gidel
63 adelL deltap .4
64 adelM deltap .5
65 delayw gasig + (adelL * ifeedback)
66
67 abuf3 delayr gidel
68 kdel line .5, p3, .001
69 adelR deltap .5 * kdel
70 delayw gasig + (adelR * ifeedback)
71 outs (adelL + adelM) * aseg, (adelR + adelM) * aseg
72 clear gasig
73 endin
74
75 </CsInstruments>
76 <CsScore>
77
78 i 1 0 2
79 i 2 1.8 5 .8
80 e
81 </CsScore>
82 </CsoundSynthesizer>";
83
create_pipeline() -> Result<gst::Pipeline, Box<dyn Error>>84 fn create_pipeline() -> Result<gst::Pipeline, Box<dyn Error>> {
85 let pipeline = gst::Pipeline::new(None);
86
87 let audio_src = gst::parse_bin_from_description(AUDIO_SRC, true)?.upcast();
88
89 let audio_sink = gst::parse_bin_from_description(AUDIO_SINK, true)?.upcast();
90
91 let csoundfilter = gst::ElementFactory::make("csoundfilter", None)?;
92 csoundfilter.set_property("csd-text", &CSD)?;
93
94 pipeline.add_many(&[&audio_src, &csoundfilter, &audio_sink])?;
95
96 audio_src.link_pads(Some("src"), &csoundfilter, Some("sink"))?;
97 csoundfilter.link_pads(Some("src"), &audio_sink, Some("sink"))?;
98
99 Ok(pipeline)
100 }
101
main_loop(pipeline: gst::Pipeline) -> Result<(), Box<dyn Error>>102 fn main_loop(pipeline: gst::Pipeline) -> Result<(), Box<dyn Error>> {
103 pipeline.set_state(gst::State::Playing)?;
104
105 let bus = pipeline
106 .bus()
107 .expect("Pipeline without bus. Shouldn't happen!");
108
109 for msg in bus.iter_timed(gst::ClockTime::NONE) {
110 use gst::MessageView;
111
112 match msg.view() {
113 MessageView::Eos(..) => break,
114 MessageView::Error(err) => {
115 println!(
116 "Error from {:?}: {} ({:?})",
117 msg.src().map(|s| s.path_string()),
118 err.error(),
119 err.debug()
120 );
121 break;
122 }
123 _ => (),
124 }
125 }
126
127 pipeline.set_state(gst::State::Null)?;
128
129 Ok(())
130 }
131
main() -> Result<(), Box<dyn Error>>132 fn main() -> Result<(), Box<dyn Error>> {
133 gst::init().unwrap();
134
135 gstcsound::plugin_register_static().expect("Failed to register csound plugin");
136
137 create_pipeline().and_then(main_loop)
138 }
139