Sound only plays once in tcl/tk (snack, pulseaudio, Linux) - linux

I'm using snack package in Linux Mint 13 (Maya), tk8.5 (wish).
My audio output is an analog stereo with pulseaudio software.
Acording to this: http://www.speech.kth.se/snack/tutorial.html
all I have to do to play a sound again is to use play command again.
I have a sound object and it only plays once no matter how many times I call the play command.
I tried putting a stop command before play, like this:
mysound stop
mysound play
What happens: it plays on the first but not on the second call, plays on the third but not on the fourth call, and it goes on. This is asynchronous, which means I pushed buttons to repeat stop-play. Now, this script:
package require snack
snack::sound s
s read knock.wav
after 1000 {s play}; #play sound effect
after 5000 {s play}; #this one doesn't work
after 10000 {s play}; #this one doesn't work
after 15000 {s stop; s play}; #played
after 20000 {s stop; s play}; #not played
after 25000 {s stop; s play}; #played
Same behavior as I had using button release events. In Android, the behavior work exactly as in theory, except that it has huge delays depending on the device (e.g. the sound comes after 2 seconds in one phone and after 200ms in another with better hardware).
I know the theory is right, and my final question is: how can I improve a Linux implementation that uses a more robust sound playing? Maybe using midi sounds. A solution that could work in any UNIX machine. Does snack provide that?
Thank you so much, for this is very important for me and I believe for other as well!

Unfortunately you don't tell us what your system is (what linux are you using and what is your audio system and device) or what you are really doing. So please provide a minimal working example.
Here is mine, that is working interactively (I routinely use Tkcon for this).
package require sound
snack::sound s1 -load longrunning-audio.wav
s1 play
# wait
s1 stop
s1 play
s1 pause
s1 pause; # resumes playing
I use the sound package instead of snack, because we don't need the graphical elements here.
And as a script
#!/usr/bin/env tclsh
package require sound
snack::sound s1 -load longrunning-audio.wav
puts "play"; s1 play
after 4000 puts "stop" \; s1 stop
after 6000 puts "play" \; s1 play
after 10000 puts "pause" \; s1 pause
after 12000 puts "resume" \; s1 pause;
after 16000 {apply {{} {
puts "stop and exit"
s1 stop
exit
}}}
# start the event loop
vwait forever
after starts a command after the given time in microseconds. In a real program you would use some procedures for this, here it is only to simulate some interaction.
Maybe you are suffering from a badly packaged snack or your audio system is playing fools with you. I remember a similar problem with some version of pulseaudio in combination with one of the output devices. Only the start of the sound was played but the audio system stayed active (use snack::audio active to show the current state).

Wow, you've got a lot of callback scripts scheduled at the same time! The after calls themselves take very little time. This means that you've got several calls to s play happening at virtually the same time. You are aware that only the last such one will have any effect? It's effectively as if you did this (in the “1000ms from now” timeslot):
s play
s play
s stop; s play
s stop; s play
s stop; s play
Yes, they're several callbacks, but they'll all actually get evaluated one after each other. You won't see any time between them.
I believe that the sound object, s, can only ever be playing or not playing. Also, sounds don't play instantly (obviously) so you've got to allow time from starting the playing to stopping it if you want the sound to be heard. Doing what you're doing will result in lots of activity at the command processing level, but not so much will be observable.

Related

How to play pre-recorded audio in reverse direction, using AudioTrak / AudioRekord IPA and Multithreading

First I write down 10 seconds of audio at the touch of a button1.
Then I want to play this record backwards by pressing a button2.
The logic is clear to me, but I can not figure out which method is responsible for reverse playback.
P.S. I will do everything with Thread or AsyncTask.

(How) Can I get a stream of all sounds recorded from the microphone that my computer did not produce? (using PulseAudio or something else)

I've been playing around with some speech-to-text and text-to-speech systems, and am running into the problem that when the computer makes sounds that it can recognize, it starts taking commands from itself. To avoid this, I'd like a stream of all sounds picked up by the microphone that were not produced by the computer itself.
I see that PulseAudio has an echo cancellation module, but so far I have been unable to distinguish between its output and the raw microphone output: it still contains all the sounds picked up by the microphone that came from the computer speakers. I wonder if the default echo canceller is doing the opposite of what I want (i.e., it removes sounds heard by the microphone from being sent to the speakers).
Any idea how I can do this (preferably with pacmd)? I have thoroughly confused myself trying to specify non-default sources for the echo canceller, and have wandered into loopback modules and other things that are probably irrelevant. I know very little about PulseAudio, haven't found a good introduction to it (I've looked through much of the PulseAudio documentation but didn't see anything relevant), and might just be missing something simple. I feel frustrated that echo cancellation apparently doesn't work, I can't find documentation on it, and I can't find examples of it working from other people.
Thanks in advance for the help!
Other details that might be relevant: I'm running Ubuntu Saucy on a Lenovo Thinkpad T410. I'm using the built-in microphone and speakers (so, I'm pretty sure they're using the same sound card and I won't have clock drift issues). My actual application gets its sound through GStreamer, but GStreamer gets it from PulseAudio, and I don't think GStreamer itself has AEC capabilities. If there's a different way of doing this, I'd gladly switch to that.
Ah, I've got it! Merely loading the echo cancellation plugin isn't enough; you then need to start using it. In particular, it will only cancel echos of sounds passed into it, and if no sounds go through it, nothing will be cancelled. So, open /etc/pulse/default.pa and add the line
load-module module-echo-cancel
towards the bottom (I put it right after the line that loads module-filter-apply). Then, restart the PulseAudio daemon by running (as a non-root user) pulseaudio -k. Next, run pacmd to get a command line interface to PulseAudio, and give it the commands list-sources and list-sinks. Note the indices of the echo canceller in the responses. Edit /etc/pulse/default.pa again, and uncomment the two lines at the end about set-default, replacing the words input and output with the indices of the echo canceller's source and sink. Finally, restart PulseAudio again with pulseaudio -k (again, run as a non-root user).
Now, by default all sounds to be output get sent through the echo canceller before heading to the speakers, and all sounds to be input get pulled from the echo canceller after coming in through the microphone, and things actually work. You can verify that it's working by running pavucontrol and looking at the sound levels on the Input Devices screen (try playing some music and speaking, and note that the echo cancelled input shows normal sound levels when you speak but very low levels (verging on nothing) when you're silent but the music is playing).
This answer mostly comes from this post, which I wish I'd found weeks ago.

Why is my Clojure project slow on Raspberry Pi?

I've been writing a simple Clojure framework for playing music (and later some other stuff) for my Raspberry Pi. The program parses a given music directory for songs and then starts listening for control commands (such as start, stop, next song) via a TCP interface.
The code is available via GitHub:
https://github.com/jvnn/raspi-framework
The current version works just fine on my laptop, it starts playing music (using the JLayer library) when instructed to, changes songs, and stops just as it should. The uberjar takes a few seconds to start on the laptop as well, but when I try to run it on the Raspberry Pi, things get insanely slow.
Just starting up the program so that all classes are loaded and the actual program code starts executing takes way over a minute. I tried to run it with the -verbose:class switch, and it seems the jvm spends the whole time just loading tons of classes (for Clojure and everything else).
When the program finally starts, it does react to the commands given, but the playback is very laggy. There is a short sub-second sound, then a pause for almost a second, then another sound, another pause etc... So the program is trying to play something but it just can't do it fast enough. CPU usage is somewhere close to 98%.
Now, having an Android phone and all, I'm sure Java can be executed on such hardware well enough to play some mp3 files without any troubles. And I know that JLayer (or parts of it) is used in the gdx game development framework (that also runs on Android) so it shouldn't be a problem either.
So everything points in me being the problem. Is there something I can do either with leiningen (aot is already enabled for all files), the Raspberry Pi, or my code that could make things faster?
Thanks for your time!
UPDATE:
I made a tiny test case to rule out some possibilities and the problems still exist with the following Clojure code:
(ns test.core
(:import [javazoom.jl.player.advanced AdvancedPlayer])
(:gen-class))
(defn -main
[]
(let [filename "/path/to/a/music/file.mp3"
fis (java.io.FileInputStream. filename)
bis (java.io.BufferedInputStream. fis)
player (AdvancedPlayer. bis)]
(doto player (.play) (.close))))
The project.clj:
(defproject test "0.0.1-SNAPSHOT"
:description "FIXME: write description"
:dependencies [[org.clojure/clojure "1.5.1"]
[javazoom/jlayer "1.0.1"]]
:javac-options ["-target" "1.6" "-source" "1.6" "-Xlint:-options"]
:aot :all
:main test.core)
So, no core.async and no threading. The playback did get a bit smoother, but it's still about 200ms music and 200ms pause.
Most obvious to me is that you have a lot of un-hinted interop code, leading to very expensive runtime reflection. Try running lein check (I think that's built in, but maybe you need a plugin) and fixing the reflection issues it points out.

Sync two soundcards

I have a program written in C++ that uses RtAudio ( Directsound ) to capture and playback audio at 48kHz samplerate.
The input capture uses a callback option. The callback writes data to a ringbuffer.
The output is a blocking write function in a separate thread that reads from the ringbuffer.
If the input and output devices are the same the audio loops thru perfectly.
Now I want to get audio from device 1 and playback on device 2. Each device has its own sampleclock set to 48kHz but are not in sync. After a couple of seconds the input and output are out of sync.
Is it possible to sync two independent oudio devices?
There are two challenges you face:
getting the two devices to start at the same time.
getting the two devices to stay in sync.
Both of these tasks are difficult. In the pro audio world, #2 is accomplished with special hardware to sync the word-clocks of multiple devices. It can also be done with a high quality video signal. I believe it can also be done with firewire devices, but I'm not sure how that works. In practice, I have used devices with no sync ("wild") and gotten very reasonable sync for up to an hour or two. Depending on what you are trying to do, the sync should not drift more than a few milliseconds over the course of a few minutes. If it does, you can consider your hardware broken (of course, cheap hardware is often broken).
As for #1, I'm not sure this is possible in any reliable sense with directsound. To the extent that it's possible with any audio API, it is difficult at best: both cards have streams that require some time to setup, open and start playing. In general, the solution is to use an API where this time is super low (ASIO, for example). This works reasonably well for applications like video, but I don't know if it really solves the problem in general.
If you really need to solve this problem, you could open both cards, starting to play silence, and use the timing information generated by the cards to establish the delay between putting data into the card and its eventual playback (this will be different for each card and probably each time you run) and use that data to calculate when to start actual playback. I don't know if RTAudio supplies the necessary timing information, but PortAudio does. This document may help.

Faking polyphony with single sound channel

I am writing music for an emulated system (Chip16), which can output ADSR formatted sound to a single channel.
Furthermore, it can only play one sound at any given time, cutting off a playing sound if necessary.
If I wanted a beat or bass playing "behind" the melody, how would I go about doing that?
Are there any tricks to simulate polyphony?
I am aware of how it was done on IBM PC speakers -- but that relied on the physical/mechanical nature of the device, which is not possible here.
For reference, the available sound instructions:
sng 0xAD, 0xVTSR ; load Attack,Decay,Volume,Type,Sustain,Release params
snp rx, D ; play sound, with frequency at [rx], for D milliseconds
snd0 ; stop currently playing sound
Thanks!

Resources