How to cache files with Perl while playing sound files using vlc? - linux

I would like to manually cache files in Perl, so when playing a sound there is little to no delay.
I wrote a program in Perl, which plays an audio file by doing a system call to VLC. When executing it, I noticed a delay before the audio started playing. The delay is usually between about 1.0 and 1.5 seconds. However, when I create a loop which does the same VLC call multiple times in a row, the delay is only about 0.2 - 0.3 seconds. I assume this is because the sound file was cached by Linux. I found Cache::Cache on CPAN, but I don't understand how it works. I'm interested in a solution without using a module. If that's not possible, I'd like to know how to use Cache::Cache properly.
(I know it's a bad idea to use a system call to VLC regarding execution speed)
use Time::HiRes;
use warnings;
use strict;
while (1) {
my $start = Time::HiRes::time();
system('vlc -Irc ./media/audio/noise.wav vlc://quit');
my $end = Time::HiRes::time();
my $duration = $end - $start;
print "duration = $duration\n";
<STDIN>;
}

Its not as easy as just "caching" a file in perl.
vlc or whatever program needs to interpret the content of the data (in your case the .wav file).
Either you stick with calling an external program and just give it a file to execute or you need to implement the whole stack in perl (and probably Perl XS Modules). By whole stack I mean:
1. Keeping the Data (your .wav file) in Memory (inside the perl runtime).
2. Interpreting the Data inside Perl.
The second part is where it gets tricky you would probably need to write a lot of code and/or use 3rd Party modules to get where you want.
So if you just want to make it work fast, stick with system calls. You could also look into Nama which might give you what you need.
From your Question it looks like you are mostly into getting the runtime of a .wav file. If its just about getting information about the File and not about playing the sound then maybe Audio::Wav could be the module for you.

Cacheing internal to Perl does not help you here.
Prime the Linux file cache by reading the file once, for example at program initialisation time. It might happen that at the time you want to play it, it has already been made stale and removed from the cache, so if you want to guarantee low access time, then put the files on a RAM disk instead.
Find and use a different media player with a lower footprint that does not load dozens of libraries in order to reduce start-up time. Try paplay from package pulseaudio-utils, or gst123, or mpg123 with mpg123-pulse.

Related

Programmatic access to a sound played through OpenAL

I am working with an application that uses OpenAL API quite extensively. In particular, there are multiple sound sources, non-trivial listener filters, etc.
I want to be able to run this application significantly faster than real-time. At the same time, the sound must be saved for later postprocessing. Is there a way to access the OpenAL output programmatically (virtually) without ever playing the sound on the real playback device?
Ideally, I'd like to have access that would be played during every tick of the main loop of my application. Normally one tick corresponds to one rendered frame (e.g. 1/30th of a second). But in this case we would be running the app as fast as possible.
We ended up using OpenAL Soft to do this. Example:
#include "alext.h"
LPALCLOOPBACKOPENDEVICESOFT alcLoopbackOpenDeviceSOFT;
alcLoopbackOpenDeviceSOFT = alcGetProcAddress(NULL,"alcLoopbackOpenDeviceSOFT");
replace your default device with this device
ALCcontext *context = alcCreateContext(device, attrs);
Set the attrs as you would for your default device
Then in the main loop use:
LPALCRENDERSAMPLESSOFT alcRenderSamplesSOFT;
alcRenderSamplesSOFT = alcGetProcAddress(NULL, "alcRenderSamplesSOFT");
alcRenderSamplesSOFT(device, buffer, 1024);
Here the buffer will store 1024 samples. This code runs faster than real-time, therefore you can sample frames every tick
Are you able to do your required functions with the audio data prior to its being shipped to OpenAL? I've done a lot with javax.sound.sampled when it is untethered by the blocking write() method in SourceDataLine, especially when saving to file rather than playing back.
From what little I know about OpenAL, there is also a blocking process occurs when data is shipped, with a queue of arrays that are managed. I've been meaning to look into this further...
(Probably not being very helpful here. Apologies.)

Node.js read and write stream to the same file at the same time

TL;DR
I'm browsing through a number of solutions on npm and github looking for something that would allow me to read and write to the same file in two different places at the same time. So far I'm having trouble actually finding anything like this. Is there a module of some sort that will allow that?
Background
In essence my requirement is that in a large file I need to, in the following order:
read
transform
write
Ideally the usage would be something like:
const fd = fs.open(file, "r+");
const read = createReadStreamSomehowFrom(fd);
const write = createWriteStreamSomehowFrom(fd);
read
.pipe(new Transform(transform() {...}))
.pipe(write);
I could do that with standard fs.create[Read/Write]Stream but there's no way to control the flow of both streams and if my write position goes beyond read position then I'm reading something I just wrote...
The use case is the same as perl -p -i -e, read and write to the same file (meaning the same inode) asynchronously and replace the contents without loading everything into memory.
I would expect this a real world use case, yet all implementations I found actually load the whole file into memory and then save it. Am I missing a known module here or is there a need to actually write something like this?
Hmm... a tough one it seems. :)
So here's for the record - I found no such module and actually discussed this with some people responsible for a nice in-file replacing module. Seeing no way to solve this I decided to write it from scratch and here it is:
signicode/rw-stream repo on github
rw-stream at npm
The module works on a simple principle that no byte can be written until it has been consumed in the readable stream and it's fairly simple underneath (couple fs.read/write ops with keeping eye on the point of read and write).
If you find this useful then I'm happy. :)

How to close file resources in pyglet

This is definitely a repeat of this question, but seeing as how that has gotten 0 replies in 3 months, and I can't seem to find an answer. The question ought to be simple: once you're done with a file (say, a video or a sound) in pyglet, how do you go about closing that file? I have an application which has to iterate over a few hundred thousand files, processing each one in turn. For obvious reasons, I am getting OSError: Too many open files. Is there a way to force-close pyglet's files?
For sound or video files you can close the current source with the Player delete() method.
You can also load the resource directly into memory instead of streaming from disk by setting the streaming argument to false in the load call:
pyglet.media.load(filename, streaming=False)
If all else fails, try forcing the garbage collector with python.gc.collect().

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.

Syncing two files when one is still being written to

I have an application (video stream capture) which constantly writes its data to a single file. Application typically runs for several hours, creating ~1 gigabyte file. Soon (in a matter of several seconds) after it quits, I'd like to have 2 copies of file it was writing - let's say, one in /mnt/disk1, another in /mnt/disk2 (the latter is an USB flash drive with FAT32 filesystem).
I don't really like an idea of modifying the application to write 2 copies simulatenously, so I though of:
Application starts and begins to write the file (let's call it /mnt/disk1/file.mkv)
Some utility starts, copies what's already there in /mnt/disk1/file.mkv to /mnt/disk2/file.mkv
After getting initial sync state, it continues to follow a written file in a manner like tail -f does, copying everything it gets from /mnt/disk1/file.mkv to /mnt/disk2/file.mkv
Several hours pass
Application quits, we stop our syncing utility
Afterwards, we run a quick rsync /mnt/disk1/file.mkv /mnt/disk2/file.mkv just to make sure they're the same. In case if they're the same, it should just run a quick check and quit fairly soon.
What is the best approach for syncing 2 files, preferably using simple Linux shell-available utilities? May be I could use some clever trick with FUSE / md device / tee / tail -f?
Solution
The best possible solution for my case seems to be
mencoder ... -o >(
tee /mnt/disk1/file.mkv |
tee /mnt/disk2/file.mkv |
mplayer -
)
This one uses bash/zsh-specific magic named "process substitution" thus eliminating the need to make named pipes manually using mkfifo, and displays what's being encoded, as a bonus :)
Hmmm... the file is not usable while it's being written, so why don't you "trick" your program into writing through a pipe/fifo and use a 2nd, very simple program, to create 2 copies?
This way, you have your two copies as soon as the original process ends.
Read the manual page on tee(1).

Resources