Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sound breaks #243

Closed
goog opened this issue Jul 2, 2016 · 16 comments
Closed

sound breaks #243

goog opened this issue Jul 2, 2016 · 16 comments
Assignees
Labels
Milestone

Comments

@goog
Copy link

goog commented Jul 2, 2016

In linux terminal , when i execute alda play --code "piano: c6 d12 e6 g12~4" one by one, repeat many times, sometime the sound ouput breaks and not good

@daveyarwood
Copy link
Member

daveyarwood commented Jul 3, 2016

Hi @goog, thanks for reporting this issue. I am able to reproduce it on OS X. It might be a while before we can get a fix worked out, but I will add it to the list of things to fix before we release version 1.0.0.

My notes are below. If anyone would like to take a stab at this, feel free! Otherwise, I'll get to it when I can :)


I'm not sure what the cause is, exactly, but I think it might have something to do with the way we maintain multiple MIDI Synthesizer instances open at once.

It takes a couple seconds to start ("open") a MIDI Synthesizer instance, so we keep a pool of them open in the background, so whenever you want to play something, the Alda process just grabs a MIDI synth that's already open and uses it. Then it "refills the pool" of MIDI synth instances. I think the sound breaking up might be due to resource contention between the threads that are playing scores and the thread that's loading new MIDI synth instances in the background.

This also might be related to using multiple JSyn SynthesisEngine instances, one per score. Technically we only need one instance that all the scores can share -- we can try doing it that way, and see if that helps. EDIT: I tried this, and it didn't help.

If none of the above helps, I had another thought - we could try turning each Alda "audio context" (i.e. one environment for playing a score - including a MIDI Synthesizer and a JSyn SynthesisEngine) into a separate process with its own JVM, and use some sort of IPC to let the Alda server find a context that's ready and give it the data it needs to play the score. That way, each Alda "performer" process wouldn't have any resource contention with all the other stuff that the Alda server needs to do, including handling HTTP requests and maintaining a pool of MIDI synths. I'm not sure how feasible this would be, just brainstorming.

@daveyarwood
Copy link
Member

#26 might help with this, too.

@daveyarwood
Copy link
Member

I'm open to other ideas on this, but I think the game plan is:

  • Try implementing smart buffering (Smart buffering #26) and see if that helps. (This is something I'd like to do anyway, for the 1.0.0 release.)
  • Try using a more direct form of IPC instead of an HTTP server (Consider alternative server format #175) - might improve performance enough to help. (Also something I'd like to try before releasing Alda 1.0.0).
  • If the problem is still occurring, then try making the change I described above where the Alda server spins off separate "performer" processes.

@erkantaylan
Copy link

I do not know clojure, so I made some tests I hope it helps.
I opened 2 different terminal and up 2 alda servers with different ports (27700 and 27701)
I wrote a simple python code to repeat the command alda.exe -p 27700(27701 for second process) play -y --code "piano: c6 d12 e6 g12~4" and writing an index
I am running on windows 10
I put the output file here https://gist.github.com/erkantaylan/3d2b13fc5a7a41c658b3413ea137399b
(I lost the data but I run before these commands with same port like ~300 times and sound is completely broken and my memory usage like 1.5gb and not decrease after stopping commands [technically a process stops immediately after playing sound?])

@daveyarwood
Copy link
Member

Remember that there are two types of Alda processes - the server and the client.

The server runs in the background continuously -- it listens for requests from the client and parses and plays scores. This is probably the cause of the continuous memory usage, even after running commands.

The client is just a command-line client that takes a command from the CLI (e.g. alda play -f score.alda), translates it into a request to the server, makes the request and exits immediately.

@daveyarwood
Copy link
Member

#26 was more or less a wash -- I was able to make a couple of tiny optimizations in the way events are scheduled, but basically, I realized that the event scheduling system we use is already very optimized such that we don't need smart buffering. I was envisioning a smart queuing system, but then I realized that we already have that, and it's working pretty well. At any rate, I'm still convinced that this is due to competing resources in the audio process, which has to both play scores and initialize new MIDI synthesizer instances in the background, so I don't think the scheduling system is the problem.

So, on to Plan B. I'd like to explore swapping out the Alda HTTP server with more direct IPC next, and see if that helps. This is probably something we would need to explore anyway if we end up going to Plan C (separate performer processes instead of a single shared one).

@daveyarwood
Copy link
Member

As of 1.0.0-rc32, we've changed the internal implementation of the server from an HTTP server to a ZeroMQ socket, which is much more lightweight and provides better performance.

@goog If you update alda to 1.0.0-rc32 by running alda update, you should see better performance from the server. I think the problem of sound breaking is a little better now, but still not totally fixed.

I'm still thinking that having the server spin off separate performer processes might be the solution. Now that we have ZeroMQ in place, we can replace the simple REQ/RES pattern we have now with an extended request-reply pattern and have the server be a broker between the client and any number of worker processes.

When the client makes a request like "play this file," the server could route the request to the next available worker, which could be a separate process with its own JVM and only one MIDI Synthesizer instance to worry about. (What we have now is a single server process that in addition to serving requests, also has to manage multiple MIDI Synthesizer instances and do all the work of parsing, evaluating and playing scores).

@elydpg
Copy link
Contributor

elydpg commented Aug 20, 2016

I'm still getting this slightly in rc32 and 33... Hard for me to tell if it's better than rc31 though since I haven't been keeping much track of this bug, letting @goog handle it.

@daveyarwood
Copy link
Member

daveyarwood commented Aug 20, 2016

I'm still getting it too -- I think the problem is really that a single server (which is also a worker) has to manage multiple scores, which means multiple MIDI synthesizer instances, etc. I'm hoping that moving to a "single server managing multiple workers" architecture will help.

@goog
Copy link
Author

goog commented Aug 23, 2016

have some improvement, but sometimes the command products no sound.

my log:

cheng@ada ~/Downloads $ alda update
Your version of alda (1.0.0-rc34) is up to date!
cheng@ada ~/Downloads $ alda play --code "piano: c6 d12 e6 g12~4"
[27713] ERROR Alda server is down. To start the server, run `alda up`.
cheng@ada ~/Downloads $ alda up
[27713] Starting Alda server...
[27713] Server up ✓
cheng@ada ~/Downloads $ alda play --code "piano: c6 d12 e6 g12~4"
[27713] Playing...
cheng@ada ~/Downloads $ alda play --code "piano: c6 d12 e6 g12~4"
[27713] Playing...
cheng@ada ~/Downloads $ alda play --code "piano: c6 d12 e6 g12~4"
[27713] Playing...
cheng@ada ~/Downloads $ alda play --code "piano: c6 d12 e6 g12~4"
[27713] Playing...
cheng@ada ~/Downloads $ alda play --code "piano: c6 d12 e6 g12~4"
[27713] Playing...
cheng@ada ~/Downloads $ alda play --code "piano: c6 d12 e6 g12~4"
[27713] Playing...
cheng@ada ~/Downloads $ alda play --code "piano: c6 d12 e6 g12~4"
[27713] Playing...
cheng@ada ~/Downloads $ alda play --code "piano: c6 d12 e6 g12~4"
[27713] Playing...
cheng@ada ~/Downloads $ alda play --code "piano: c6 d12 e6 g12~4"
[27713] Playing...
cheng@ada ~/Downloads $ alda play --code "piano: c6 d12 e6 g12~4"
[27713] Playing...
cheng@ada ~/Downloads $ alda play --code "piano: c6 d12 e6 g12~4"
[27713] Playing...
cheng@ada ~/Downloads $ alda play --code "piano: c6 d12 e6 g12~4"
[27713] Playing...
cheng@ada ~/Downloads $ alda play --code "piano: c6 d12 e6 g12~4"
[27713] Playing...
cheng@ada ~/Downloads $ alda play --code "piano: c6 d12 e6 g12~4"
[27713] Playing...
cheng@ada ~/Downloads $ alda play --code "piano: c6 d12 e6 g12~4"
[27713] Playing...
cheng@ada ~/Downloads $ alda play --code "piano: c6 d12 e6 g12~4"
[27713] Playing...
cheng@ada ~/Downloads $ alda play --code "piano: c6 d12 e6 g12~4"
[27713] Playing...
cheng@ada ~/Downloads $ alda play --code "piano: c6 d12 e6 g12~4"
[27713] Playing...
cheng@ada ~/Downloads $ alda play --code "piano: c6 d12 e6 g12~4"
[27713] Playing...
cheng@ada ~/Downloads $ alda play --code "piano: c6 d12 e6 g12~4"
[27713] Playing...
cheng@ada ~/Downloads $ alda play --code "piano: c6 d12 e6 g12~4"
[27713] Playing...
cheng@ada ~/Downloads $ alda play --code "piano: c6 d12 e6 g12~4"
[27713] Playing...
cheng@ada ~/Downloads $ alda play --code "piano: c6 d12 e6 g12~4"
[27713] Playing...
cheng@ada ~/Downloads $ alda play --code "piano: c6 d12 e6 g12~4"
[27713] Playing...
cheng@ada ~/Downloads $ alda play --code "piano: c6 d12 e6 g12~4"
[27713] Playing...
cheng@ada ~/Downloads $ alda play --code "piano: c6 d12 e6 g12~4"
[27713] Playing...
cheng@ada ~/Downloads $ alda play --code "piano: c6 d12 e6 g12~4"
[27713] Playing...
cheng@ada ~/Downloads $ alda play --code "piano: c6 d12 e6 g12~4"
[27713] Playing...
cheng@ada ~/Downloads $ alda play --code "piano: c6 d12 e6 g12~4"
[27713] Playing...
cheng@ada ~/Downloads $ alda play --code "piano: c6 d12 e6 g12~4"
[27713] ERROR Alda server is down. To start the server, run `alda up`.
cheng@ada ~/Downloads $ alda up
[27713] Starting Alda server...
[27713] Server down ✗
cheng@ada ~/Downloads $ 

@daveyarwood
Copy link
Member

Interesting... from the terminal output, it looks like the server eventually gets so bogged down by all the simultaneous requests that it becomes unresponsive.

I think moving to the "single server managing multiple workers" architecture will definitely help -- that's the next step.

@goog
Copy link
Author

goog commented Aug 24, 2016

maybe a single server plus a working code queue works for this case.

@daveyarwood
Copy link
Member

A work queue is also a good idea. If there are no workers available (e.g.
if you have three workers and you're already playing 3 scores), we could
block until one is available. Or maybe even have the server respond that no
workers are available, and ask you to wait until playback is done before
playing another score.

On Aug 23, 2016 9:32 PM, "Jay Cheng" notifications@github.com wrote:

maybe a single server plus a working queue


You are receiving this because you were assigned.
Reply to this email directly, view it on GitHub
#243 (comment), or mute
the thread
https://github.com/notifications/unsubscribe-auth/AEroF7BycgnkWbsTQ3YosxPKk6GWOPasks5qi58YgaJpZM4JDxCT
.

@daveyarwood
Copy link
Member

I'll also experiment with the workers just being threads on the server process, instead of separate processes. It seems like maybe the issue isn't having multiple MIDI synth instances open, but trying to initialize a new instance while another instance is playing something. I can try setting it up so that we have (for example) 5 worker threads, each with its own reusable MIDI synth instance, and when you reach the point where you have 5 scores playing at the same time, there won't be any workers available, so the server can either block or tell you to wait.

Both ways have their own advantages (worker threads on the server process, vs. separate worker processes). Worker threads are lower-latency, but if we do worker processes, then the workers won't have to compete for resources. I'll try it both ways and see which one performs better.

@daveyarwood
Copy link
Member

Fixed in 1.0.0-rc35. (Take care to read the "TL;DR" at the top of the changelog before updating!)

@goog Please feel free to re-open if you're still experiencing problems with sound breaking up after updating.

@elydpg
Copy link
Contributor

elydpg commented Sep 22, 2016

Still getting this occasionally. Using the REPL (because of everything going on with the server I am resisting using it for now) however I would think its affected on both.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants