2020-01-10 01:52:31 +00:00
// Copyright (C) 2020 Natanael Mojica <neithanmo@gmail.com>
//
2022-01-15 18:40:12 +00:00
// This Source Code Form is subject to the terms of the Mozilla Public License, v2.0.
// If a copy of the MPL was not distributed with this file, You can obtain one at
// <https://mozilla.org/MPL/2.0/>.
2020-01-10 01:52:31 +00:00
//
2022-01-15 18:40:12 +00:00
// SPDX-License-Identifier: MPL-2.0
2020-01-10 01:52:31 +00:00
use gst ::prelude ::* ;
use std ::error ::Error ;
const AUDIO_SRC : & str = " audiotestsrc " ;
const AUDIO_SINK : & str = " audioconvert ! autoaudiosink " ;
// This example defines two instruments, the first instrument send to the output that is at its input and accumulates the received audio samples
// into a global variable called gasig. The execution of this instrument last the first 2 seconds.
// The second instrument starts it execution at 1.8 second, This instrument creates two audio buffers with samples that are read
// from the global accumulator(gasig), then reads these buffers at a fixed delay time, creating the adelL, adelM and adelR buffers,
// 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.
// Finally, those buffers are mixed with the accumulator, and an audio envelop is applied(aseg) to them.
2023-04-10 11:34:46 +00:00
// The result is similar to an audio echo in which the buffered samples are read at different delay times and also modified in frequency(right channel),
2020-01-10 01:52:31 +00:00
// this creates an space effect using just one channel audio input.
const CSD : & str = "
< CsoundSynthesizer >
< CsOptions >
< / CsOptions >
< CsInstruments >
sr = 44100
ksmps = 7
2021-06-03 18:20:54 +00:00
nchnls_i = 1
nchnls = 2
2020-01-10 01:52:31 +00:00
gasig init 0
2021-06-03 18:20:54 +00:00
gidel = 1
2020-01-10 01:52:31 +00:00
instr 1
ain in
outs ain , ain
2021-06-03 18:20:54 +00:00
vincr gasig , ain
2020-01-10 01:52:31 +00:00
endin
instr 2
ifeedback = p4
2021-06-03 18:20:54 +00:00
aseg linseg 1. , p3 , 0.0
2020-01-10 01:52:31 +00:00
abuf2 delayr gidel
adelL deltap . 4
adelM deltap . 5
delayw gasig + ( adelL * ifeedback )
abuf3 delayr gidel
kdel line . 5 , p3 , . 001
adelR deltap . 5 * kdel
delayw gasig + ( adelR * ifeedback )
outs ( adelL + adelM ) * aseg , ( adelR + adelM ) * aseg
clear gasig
endin
< / CsInstruments >
< CsScore >
i 1 0 2
i 2 1.8 5 . 8
e
< / CsScore >
< / CsoundSynthesizer > " ;
fn create_pipeline ( ) -> Result < gst ::Pipeline , Box < dyn Error > > {
2022-10-22 16:06:29 +00:00
let pipeline = gst ::Pipeline ::default ( ) ;
2020-01-10 01:52:31 +00:00
2023-12-04 14:54:00 +00:00
let audio_src = gst ::parse ::bin_from_description ( AUDIO_SRC , true ) ? . upcast ( ) ;
2020-01-10 01:52:31 +00:00
2023-12-04 14:54:00 +00:00
let audio_sink = gst ::parse ::bin_from_description ( AUDIO_SINK , true ) ? . upcast ( ) ;
2020-01-10 01:52:31 +00:00
2022-10-19 16:18:43 +00:00
let csoundfilter = gst ::ElementFactory ::make ( " csoundfilter " )
2022-11-01 08:27:48 +00:00
. property ( " csd-text " , CSD )
2022-10-19 16:18:43 +00:00
. build ( )
. unwrap ( ) ;
2020-01-10 01:52:31 +00:00
2023-03-09 15:30:57 +00:00
pipeline . add_many ( [ & audio_src , & csoundfilter , & audio_sink ] ) ? ;
2020-01-10 01:52:31 +00:00
audio_src . link_pads ( Some ( " src " ) , & csoundfilter , Some ( " sink " ) ) ? ;
csoundfilter . link_pads ( Some ( " src " ) , & audio_sink , Some ( " sink " ) ) ? ;
Ok ( pipeline )
}
fn main_loop ( pipeline : gst ::Pipeline ) -> Result < ( ) , Box < dyn Error > > {
pipeline . set_state ( gst ::State ::Playing ) ? ;
let bus = pipeline
2021-04-12 12:49:54 +00:00
. bus ( )
2020-01-10 01:52:31 +00:00
. expect ( " Pipeline without bus. Shouldn't happen! " ) ;
2021-05-25 14:37:48 +00:00
for msg in bus . iter_timed ( gst ::ClockTime ::NONE ) {
2020-01-10 01:52:31 +00:00
use gst ::MessageView ;
match msg . view ( ) {
MessageView ::Eos ( .. ) = > break ,
MessageView ::Error ( err ) = > {
println! (
" Error from {:?}: {} ({:?}) " ,
2021-04-12 12:49:54 +00:00
msg . src ( ) . map ( | s | s . path_string ( ) ) ,
err . error ( ) ,
err . debug ( )
2020-01-10 01:52:31 +00:00
) ;
break ;
}
_ = > ( ) ,
}
}
pipeline . set_state ( gst ::State ::Null ) ? ;
Ok ( ( ) )
}
fn main ( ) -> Result < ( ) , Box < dyn Error > > {
gst ::init ( ) . unwrap ( ) ;
gstcsound ::plugin_register_static ( ) . expect ( " Failed to register csound plugin " ) ;
create_pipeline ( ) . and_then ( main_loop )
}