philburk / jsyn Goto Github PK
View Code? Open in Web Editor NEWModular audio synthesizer library with unit generators in Java
Home Page: http://www.softsynth.com/jsyn
License: Apache License 2.0
Modular audio synthesizer library with unit generators in Java
Home Page: http://www.softsynth.com/jsyn
License: Apache License 2.0
keypressed counters in SoundTweaker could use labels for explanation or perhaps be removed.
Hello!
I created a repackaging project at https://github.com/jjYBdx4IL/jsyn-repack for deployment of jsyn to maven central.
Some tests (ie. com.jsyn.unitgen.TestConnections) are not working as expected. Take a look at them if you want. Otherwise I'll just go on and deploy it because basic output tests seem to be working okay.
Replace code in sample file I/O that manually shuffles bytes.
This is probably more of a confusing warning than a helpful one. segEnv is generally connected to monoReader which is exported, and actually the segEnv data is sort of exported... so seeing the warning that segEnv will not be exported is probably not helpful.
I think those warnings should be reserved for compositional units like sequencers and knobs
I am following the example code in the programmers guide, but I found out that this won't even initialize. I have searched Google and haven't quite found the fix.
Here's my code:
Synthesizer synth = JSyn.createSynthesizer();
synth.start();
LineOut out = new LineOut();
WhiteNoise noise = new WhiteNoise();
noise.output.connect(out);
synth.add(out);
synth.add(noise);
try{Thread.sleep(4);}catch(Exception e){}
synth.stop();
all in main
. The error is:
PulseAudioMixer: got interrupted while waiting for the EventLoop to initialize
java: /build/openjdk-8-TuolsG/openjdk-8-8u171-b11/icedtea-sound/src/native/jni-common.c:96: getJavaByteArrayField: Assertion `array' failed.
Any reason anyone knows as to why this is happening or at least a workaround?
I tested new fader behavior by connecting fader to frequency aInput of a Voice and confirm that if unedited, the fader takes on the min/max/default of the aInput and if edited, fader values will not be affected by aInput. This is nice.
Suggestion: I think that if I edit a fader and then connect it, it should kick the value into the aInput. So for example if I set fader value to 220 and connect it to frequency, I expect to hear the osc change tone. Either that, or it would be nice to have a kick on the fader itself so that after I connect it, I can just kick it with my mouse and it'll send the current value to the aInput. (I know I can open the fader edit and kick it like that, or connect a kick to it). But as a convenience, I think a kick on the fader itself where the user can click would be helpful.
Keep a command list with the data necessary to reverse the command.
For example, when deleting units, copy them first to XML and store the XML attached to a Delete command on the Undo stack
UnitOutputPort on exported Syntona unitVoice has two parts instead of one.
Expected behavior: the simple SineVoice attached should have a one part output but has two instead.
Note the "public UnitOutputPort voice;" in addition to "public UnitOutputPort output;" in exported source (commented by me)
Note also main() method I added which shows that output has two parts
Current behavior which is expected and good:
Editing a subpatch and saving Top results in edits to subpatch being saved, because the Top xml includes all units and connections required to rebuild the subpatch. So the user gets into a development cycle of editing the subpatch, jumping to Top, listening, diving back into the subpatch to make more edits, etc... and is assured that saving the Top will result in an XML that recreates latest and complete state of the work.
Here's where the trouble starts: once user saves a subpatch as a separate XML, the top patch saves a link to the subpatch filename. This is not bad, but user is unaware of this change to the XML file structure and its consequences.
Further edits by user to the subpatch are not saved when user saves the Top. User is unaware of this behavior change.
This is bad because the user expectation is that saving the Top saves all changes, so later when the user reopens the Top xml, any changes since the subpatch was saved as a separate XML are not there.
Maybe a good solution is for File menu to explicitly require the user to make a choice. There's "Save current patch (with links)" and there's "Save bundle". The former works as Save currently does, writing links when possible. The latter dives into all subpatches and puts everything into a single XML with no links. The bundle is the guaranteed-to-work recreation of current state. This would be good because it exposes the idea to the user. You might also consider disabling the "with links" save menu item, until the state of the patch is such that links will be written. So in the example above, once the user saves a subpatch, the menu item to save with links is enabled, driving the idea home.
So friends can play with a patch and not mess up the connections, or move things, or add or subtract modules.
I would like to have a unit that references WAV samples on disk, and outputs them in sample form.
private static final boolean useSample = true;
private final static boolean useRecorder = false;
// File sampleFile = new File( "samples/instructions.wav" );
File sampleFile = new File(
// "/Users/phil/Work/jsyn/guitar100/Guitar100_Ocean_1#02.aif" );
"/Users/phil/Music/samples/ChewyMonkeysWhistle.aiff" );
/* Can be run as either an application or as an applet. */
public static void main( String args[] )
{
...
synth.add( grainFarm );
grainFarm.allocate( NUM_GRAINS );
// Add an output so we can hear the grains.
synth.add( lineOut = new LineOut() );
grainFarm.getOutput().connect( 0, lineOut.input, 0 );
grainFarm.getOutput().connect( 0, lineOut.input, 1 );
// Start synthesizer using default stereo output at 44100 Hz.
synth.start();
// Start lineOut so it can pull data from other units.
lineOut.start();
if( useRecorder )
{
grainFarm.output.connect( 0, recorder.getInput(), 0 );
// When we start the recorder it will pull data from the
// oscillator
// and sweeper.
recorder.start();
}
setupGUI();
// We only need to start the LineOut. It will pull data from the
// oscillator.
lineOut.start();
I think it would be helpful to document SequentialDataCommon
setSustainBegin better (I don't believe there's any javadoc comment for
it currently). I'd even suggest a simple diagram of, say a four frame
breakpoint envelope with the frames labelled 0, 1, 2, 3 and arrows
showing from where to where it'll loop based on setSustainBegin and
setSustainEnd. Same from setReleaseBegin/End
GitHub has a Packages section that can be used to simplify the process.
When I double click on a unit to open its editor dialog, I notice the textfield with the name of the unit is in red as though it were cueing me that the name has changed even though it hasn't .
The expected behavior, from my POV, is that the textfield would be white when the edit window first opens. Then if I make a change it should turn red, until I hit return, then it should turn white again
Not a major issue but still important.
The last line of NOTICE.txt
Lisa Tolenti converted many of the unit generators from 'C' to Java in 2009.
should be changed to
Lisa Tolentino converted many of the unit generators from 'C' to Java in 2009.
For proof see: http://lisatolentino.com/, projected is reference at the very bottom.
I want to use VariableRateDataReader play t tone with SegmentedEnvelope.I know it can control the volume of tone.But how can I implement the different volume for left and right channel?
Thanks!
When starting the synthesizer engine with a count of devices greater than two utilising the PortAudio bindings the library just crashes. It does work when just specifying the number of device inputs to two.
I am trying this on a Mac (10.15.6) with the JNIlibs properly linked.
Also to add the output from the logs of the JSyn lib:
Audio input from Rane Seventy-Two Audio - Core Audio JPortAudio: 64-bit requestedFramesPerBuffer = 128, coreAudioBufferSizeFrames = 384 ringBufferSize after = 2048
^^ The above shows that it's initialising the device, and then allocating the ringBufferSize, however then it appears lower down in src/hostapi/coreaudio/pa_mac_core_blocking.c, it doesn't like that size as from initializeBlioRingBuffers it get's a SIGABRT
All I'm trying to achieve is getting specific inputs for two specific line ins for a soundcard (a bit like the DualOscilloscope example ) However, I'm having absolutely no luck.
Here is the output I'm getting as a general crash for the system:
System Integrity Protection: enabled Crashed Thread: 37 Java: DefaultDispatcher-worker-1 @coroutine#130
Exception Type: EXC_BAD_ACCESS (SIGABRT)
Exception Codes: KERN_INVALID_ADDRESS at 0x0000000000000008
Exception Note: EXC_CORPSE_NOTIFY
VM Regions Near 0x8:
__TEXT 00000001041fe000-00000001041ff000 [ 4K] r-x/rwx SM=COW /Library/Java/JavaVirtualMachines/jdk-14.0.1.jdk/Contents/Home/bin/java
Application Specific Information:
Assertion failed: (!err), function initializeBlioRingBuffers, file /Users/phil/Work/portaudio/pav19/build/macosx/MacPA/MacPA/../../../../src/hostapi/coreaudio/pa_mac_core_blocking.c, line 177.
Here is the code:
fun simpleLineInExample(){ val lineIn: LineIn val lineOut: LineOut
// Create a context for the synthesizer.
// Create a context for the synthesizer.
val synth = JSyn.createSynthesizer()
// Add an audio input.
synth.add(LineIn().also { lineIn = it })
// Add an audio output.
synth.add(LineOut().also { lineOut = it })
// Connect the input to the output.
lineIn.output.connect(0, lineOut.input, 0)
lineIn.output.connect(1, lineOut.input, 1)
// Both stereo.
// Both stereo.
val numInputChannels = 14 // (I know the soundcard has this many, but I could get it from device info)
val numOutputChannels = 2
synth.stop()
synth.start(
44100, AudioDeviceManager.USE_DEFAULT_DEVICE, numInputChannels,
AudioDeviceManager.USE_DEFAULT_DEVICE, numOutputChannels
)
// We only need to start the LineOut. It will pull data from the LineIn.
lineOut.start()
// Sleep a while.
try {
val time = synth.currentTime
// Sleep for a few seconds.
synth.sleepUntil(time + 8.0)
} catch (e: InterruptedException) {
e.printStackTrace()
}
// Stop everything.
synth.stop()
}`
In Syntona, the caps lock key is used to enable/disable 'Play Keys' mode. On my Linux Ubuntu w/ unity desktop, when I click caps lock, the checkbox next to 'Caps Lock (play keys)' is enabled, but then disables itself immediately. Typing in a terminal shows that the caps lock is enabled outside of Syntona. I don't see this behavior on Windows or Mac OS X. I am still able to click the checkbox to keep it enabled manually.
When Play Keys is checked , I am unable to change the value of YMax textfield in SegEnv Editor
I want to consume this library in one android-application - looks really useful and seems to work nice - but currently I would have to drop in the jar which I do not find appealing. My solution now is to use @jitpack which points to a fork of jsyn where I added gradle build-files:
also there I removed JPortAudioDevice and the corresponding dependency as I do not want this on android. Ideally I would see 3 artifacts here jsyn-core, then jsyn-android ( depends on core ) and jsyn-portaudio ( also depends on core ).
Not sure what your take on this is - could also provide a PR in this direction but would like to know your opinion on this before. Do you want to keep ant? What do you think about splitting into 3 artifacts?
cc @ptrv
I noticed the WARNING: at the top bar area of the Voice editor for units that don't export to Java. This is nice!
I noticed it, though, when I copied and pasted two Clocks and two Shows from the Top into the Voice. The Voice warning only had room to let me know Show2 would not be exported.
Suggestion: have the Warning be a button that appears instead of a message, maybe labelled "Java Export Warning". Clicking it opens a little JFrame with a text area which enumerates all the things that cannot export to Java.
Also it would be helpful to specify "...not be exported to Java" instead of just "not be exported". A new Syntona user might get that confused with "will not be saved"
it would be very convenient to have Sound Font support in Jsyn- this would make the wide range of sample-based synthesis instruments available.
Hi Phil,
I'm working on a "theremin-simulator" based on parts of the code in UseMidiKeyboard.java.
I want to be able to change midi input (keyboard) while the program runs, via a menu option.
Then I have problems, concentrating on the function test() in UseMidiKeyboard.java:
I also tried to use synth.stop() and start() but that made no difference.
Maybe you have a suggestion what to do?
kind regards,
Paul
Working on OSX 10.9.5 with the latest jsyn.
Here: https://github.com/philburk/jsyn/blob/master/src/com/jsyn/engine/SynthesisEngine.java#L236
If engineThread.getPriority > 8 then an IAE will be thrown
I'm trying to play Jsyn through a bluetooth speaker connected to raspberry pi 3b+.
If I run "aplay test.wav" in terminal, it plays through the bluetooth speaker with no problem.
However, if I play pink noise with Jsyn through Bluetooth, it only plays short burst (like 30ms) at a time with gaps.
If I play Jsyn through pi 3.5mm output, it works fine.
Any help would be appreciated!
Since Syntona already has a copy and paste and delete, it would be very helpful to have a Cut (ie delete that pastes).
I noticed this need when I wanted to move units out of the Top and into a Voice (or vice versa)
App running for 40 minutes before this crash:
java.lang.ArrayIndexOutOfBoundsException: 44100
at com.jsyn.data.ShortSample.readDouble(ShortSample.java:108)
at com.jsyn.ports.UnitDataQueuePort.readNextMonoDouble(UnitDataQueuePort.java:274)
at com.jsyn.unitgen.VariableRateMonoReader.advanceToNextFrame(VariableRateMonoReader.java:100)
at com.jsyn.unitgen.VariableRateMonoReader.generate(VariableRateMonoReader.java:57)
at com.jsyn.engine.SynthesisEngine.synthesizeBuffer(SynthesisEngine.java:517)
at com.jsyn.engine.SynthesisEngine.generateNextBuffer(SynthesisEngine.java:429)
at com.jsyn.engine.SynthesisEngine.run(SynthesisEngine.java:373)
at java.lang.Thread.run(Thread.java:745)
Nov 27, 2016 2:46:08 PM com.jsyn.engine.SynthesisEngine run
INFO: JSyn synthesis thread in finally code.
OSX, 10.10
JPortAudio version 1899, PortAudio V19-devel (built Sep 4 2012 12:46:22)
java.version = 1.8.0_31, java.vendor = Oracle Corporation, os.arch = x86_64
Nov 27, 2016 2:00:31 PM com.jsyn.engine.SynthesisEngine start
INFO: Pure Java JSyn from www.softsynth.com, rate = 44100, RT, V16.7.3 (build 457, 2014-12-25)
Sample queuing allows queuing past the end of the sample. Check at top queue() call and issue IllegalArgumentException instead of this:
java.lang.ArrayIndexOutOfBoundsException: 44100
at com.jsyn.data.ShortSample.readDouble(ShortSample.java:108)
at com.jsyn.ports.UnitDataQueuePort.readNextMonoDouble(UnitDataQueuePort.java:274)
at com.jsyn.unitgen.VariableRateMonoReader.advanceToNextFrame(VariableRateMonoReader.java:100)
at com.jsyn.unitgen.VariableRateMonoReader.generate(VariableRateMonoReader.java:57)
at com.jsyn.engine.SynthesisEngine.synthesizeBuffer(SynthesisEngine.java:517)
at com.jsyn.engine.SynthesisEngine.generateNextBuffer(SynthesisEngine.java:429)
at com.jsyn.engine.SynthesisEngine.run(SynthesisEngine.java:373)
at java.lang.Thread.run(Thread.java:745)
I am working on an app that wants to dynamically load Syntona XML circuits into Jsyn. I am aware of "Export to Java", but that requires me to recompile the application every time I want to add a new patch. It wasn't clear to me if I should add syntona.jar to my app, and use that to create a patch, or whether the code could be in jsyn.jar.
...
It then adds a method:
public UnitOutputPort getOutput() {
return output;
}
This will not compile. Export should just display an error message.
I imagine such a thing exists already, but don't see it in the examples. Want to verify before trying to implement one... Does such a thing exist?
It demonstrates how to use the multi-channel features.
Nick wrote:
Notice this in http://softsynth.com/jsyn/docs/usersguide.php
ShortSample clarinetSample = SampleLoader.loadShortSample(file);
myTable = new DoubleTable( clarinetSample );
But there is no loadShortSample() method in SampleLoader.
There is loadFloatSample()
But DoubleTable( clarinetSample ) does not take a FloatSample
I am interested in trying a live input with PlayGrains, rather than a sample. I am guessing this would require e a new implementation of GrainSource, something like 'InputGrainSource', that extends GrainCommon. But I'm at a loss beyond that... ?
If I set the cutoff frequency for a FilterFourPole to 0.0 then the output would become too large and hit NaN in less than a second.
The input frequency gets clipped internally to MINIMUM_FREQUENCY, which was 0.00001. But that was too low. I now set it to 1.0.
When I change YMax in SegEnv and then close the the SegEnv editor, the value I changed it to is not restored in the YMax TextField when I reopen the SegEnv editor
java.lang.ArrayIndexOutOfBoundsException: 352800
at com.jsyn.data.ShortSample.readDouble(ShortSample.java:108)
at com.jsyn.ports.UnitDataQueuePort.readNextMonoDouble(UnitDataQueuePort.java:274)
at com.jsyn.unitgen.VariableRateMonoReader.advanceToNextFrame(VariableRateMonoReader.java:100)
at com.jsyn.unitgen.VariableRateMonoReader.generate(VariableRateMonoReader.java:57)
at com.jsyn.engine.SynthesisEngine.synthesizeBuffer(SynthesisEngine.java:517)
at com.jsyn.engine.SynthesisEngine.generateNextBuffer(SynthesisEngine.java:429)
at com.jsyn.engine.SynthesisEngine.run(SynthesisEngine.java:373)
at java.lang.Thread.run(Thread.java:745)v
Not sure how to recreate (happened after 20 minutes of using a JSyn-based app)
---- JPortAudio version 1899, PortAudio V19-devel (built Sep 4 2012 12:46:22)
java.version = 1.8.0_31, java.vendor = Oracle Corporation, os.arch = x86_64
OSX 10.10
Broken link from..
http://www.softsynth.com/jsyn/docs/usersguide.php#CreatingEnvelopes
to:
http://www.softsynth.com/jsyn/docs/javadocs/com/jsyn/unitgen/SegmentedEnvelope.html
Look for link in sentence "Envelope data is stored internally in a
SegmentedEnvelope object."
The old SynthTable class had one.
Reported by Alan Fabian.
It seems like there are issues with the jsyn api on some phones producing crackling and buffer under runs.
So far from the devices I managed to get a hand on the issue occurs on LG-G2, LG-G3, LG-K10. This does
not confirm this is an LG specific issue, but might be a hint.
Even simple projects cause this issue, for example:
https://play.google.com/store/apps/details?id=p.purechords.windfilterpure
source: https://github.com/faxinadu/WindFilterPure
and
https://play.google.com/store/apps/details?id=p.purechords.aeolianmeditation
I have tried setting these (even though Android Studio says 'Private field suggestedOutputLatency is assigned but never accessed')
from
private double suggestedOutputLatency = 0.100;
private double suggestedInputLatency = 0.100;
to
private double suggestedOutputLatency = 2.00;
private double suggestedInputLatency = 2.00;
I have also tried setting from
@OverRide
public int setSuggestedOutputLatency( double latency )
{
suggestedOutputLatency = latency;
return 0;
}
to
@OverRide
public int setSuggestedOutputLatency( double latency )
{
suggestedOutputLatency = 2.00;
return 0;
}
In the logcat, i get this line appearing on LG-K10:
04-20 10:30:14.883 31164-31572/p.purechords.aeolianmeditation W/AudioTrack: releaseBuffer() track 0xb83470a0 disabled due to previous underrun, restarting
It would be very useful to load external time/data events from a specialized input unit in Syntona. This would allow precreating (for example) a series of pitches or frequencies with timings, then repeatedly playing through various patches for experimentation. The input unit should have a configurable filename input, which can either be edited as a string in the unit, or provided by an control like 'value'.
Iโm trying to update some legacy (old jsyn api) code to specify input/output devices other than the default (this is how it was originally coded).
The current code uses:
Synth.start(int flags, double frameRate);
I get the error when I change to:
Synth.start(int flags, double frameRate, int inputDeviceID,
int numInputChannels, int outputDeviceID, int numOutputChannels);
Here is my code:
Synth.initialize();
int inDevID = AudioDevice.getDefaultInputDeviceID();
int outDevID = AudioDevice.getDefaultOutputDeviceID();
int inDevChNum = AudioDevice.getMaxInputChannels(inDevID);
int outDevChNum = AudioDevice.getMaxOutputChannels(outDevID);
Synth.start(flag, rate, inDevID, inDevChNum, outDevID, outDevChNum);
Synth.setTrace(Synth.SILENT);
And the error:
Jul 30, 2016 8:05:09 PM com.jsyn.engine.SynthesisEngine start
INFO: Pure Java JSyn from www.softsynth.com, rate = 44100, RT, V16.7.3 (build 457, 2014-12-25)
Jul 30, 2016 8:05:09 PM com.jsyn.engine.SynthesisEngine run
INFO: JSyn synthesis thread in finally code.
Jul 30, 2016 8:05:10 PM com.jsyn.engine.SynthesisEngine start
INFO: Pure Java JSyn from www.softsynth.com, rate = 44100, RT, V16.7.3 (build 457, 2014-12-25)
java.lang.NullPointerException
at com.jsyn.devices.javasound.JavaSoundAudioDevice$JavaSoundOutputStream.write(JavaSoundAudioDevice.java:264)
at com.jsyn.devices.javasound.JavaSoundAudioDevice$JavaSoundOutputStream.write(JavaSoundAudioDevice.java:231)
at com.jsyn.engine.SynthesisEngine.run(SynthesisEngine.java:379)
at java.lang.Thread.run(Thread.java:745)
Jul 30, 2016 8:05:10 PM com.jsyn.engine.SynthesisEngine run
INFO: JSyn synthesis thread in finally code.
java.lang.RuntimeException: AudioOutput stop attempted when no line created.
at com.jsyn.devices.javasound.JavaSoundAudioDevice$JavaSoundOutputStream.stop(JavaSoundAudioDevice.java:278)
at com.jsyn.engine.SynthesisEngine.run(SynthesisEngine.java:398)
at java.lang.Thread.run(Thread.java:745)
REPRODUCE
Run example AudioPassThrough
EXPECT
Hear audio from input echod to output.
ACTUAL
No audio input.
ADDITIONAL
One problem is if the Macbook does not have any USB interface attached.
The start() will fail. The built-in speaker is mono but the app requests stereo.
Connecting a stereo audio interface helps.
But then we get the silence. This seems related to new Apple privacy rules related to microphones.
Bug for OpenJDK - Resolved May 2020-05
https://bugs.openjdk.java.net/browse/JDK-8244951
Related bugs for AdoptOpenJDK
adoptium/adoptium-support#222
adoptium/temurin-build#1720
Mac tech help for enabling an app
https://help.uaudio.com/hc/en-us/articles/360050791811-macOS-11-Big-Sur-Apple-M1-Compatibility-Info
https://developer.apple.com/documentation/avfoundation/cameras_and_media_capture/requesting_authorization_for_media_capture_on_macos
Oracles OpenJDK for Mac
https://jdk.java.net/
Installation Instructions at:
https://java.tutorials24x7.com/blog/how-to-install-openjdk-14-on-mac
I installed JDK 16 but Mac says it is corrupt. It seems to me that Oracle is trying to destroy Java and has successfully killed it on the Mac.
So I may need to switch to Linux or switch to another language! The Mac is becoming increasingly unfriendly to developers. And I don't know of a good cross platform language environment.
Is there a Rust UI? https://linebender.org/druid/
https://flutter.dev/
https://developer.android.com/jetpack/compose
[email protected] reported that with 32 samples, and frequencies centered in a bin, that the JSyn FFT produces results very different from other known good FFT implementations.
Try SVF trapezoidal filters from Andrew Simper
http://www.cytomic.com/technical-papers
I find that adding Kicks, clocks, Double inputs, faders, and shows happen to frequently that it would be great to have shortcut keys that add them to a patch
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.