Orgs in Java

Dec 21, 2011 at 4:05 PM
graters gonna grate
"Heavy swords for sale. Suitable for most RPG Protagonists. Apply now!"
Join Date: Jul 2, 2008
Location: &
Posts: 1886
Age: 32
Pronouns: he/him
Ah, thanks about the pi thing. I had figured out all that about the freq, though I didn't feel like explaining it in the first post.
 
Dec 23, 2011 at 7:08 AM
Senior Member
"This is the greatest handgun ever made! You have to ask yourself, do I feel lucky?"
Join Date: Jul 11, 2009
Location: Texas, USA
Posts: 90
Pronouns: he/him
I posted some of my measurements and examinations of the sounds OrgMaker makes: OrgMaker Notes.
 
Dec 23, 2011 at 3:44 PM
graters gonna grate
"Heavy swords for sale. Suitable for most RPG Protagonists. Apply now!"
Join Date: Jul 2, 2008
Location: &
Posts: 1886
Age: 32
Pronouns: he/him
Interesting. It seems I've been doing volume totally wrong :o. Also, in this image:

p111630-0-octave3.png


The little squiggles around where it reaches zero suggest that some sinc interpolation is going on. Implementing this in my program would probably fix the thing where certain melody instruments sound shrieky and distorted (i.e. the main melody instrument in "Arctic Frolic" from TWoR).
 
Dec 23, 2011 at 7:32 PM
Senior Member
"This is the greatest handgun ever made! You have to ask yourself, do I feel lucky?"
Join Date: Jul 11, 2009
Location: Texas, USA
Posts: 90
Pronouns: he/him
Wedge of Cheese said:
Interesting. It seems I've been doing volume totally wrong :p.

I've only tested on the two sound cards on my computer. It may be OrgMaker just giving a volume level to DirectX and then DirectX is somehow deciding what amplitude to output? I don't know if the amplitudes might vary if there's a different DirectX version installed. I tried to explain the steps so if anyone really wants to they can confirm if it works the same on their computer.

I was originally motivated to measure the volume and pan amplitudes because when I was making my ORG-to-MIDI converter, the MIDI volume levels sounded different than the ORG. I thought, how can I make it sound the same? I realized I could try to get the amplitudes to match and it might sound better.

Wedge of Cheese said:
The little squiggles around where it reaches zero suggest that some sinc interpolation is going on.

Well, I just recorded from my sound card's "Stereo Mix", so I just thought they were digital to analog to digital artifacts? I didn't expect the wave in Audacity to be a bit-for-bit perfect match to what OrgMaker was outputting, but it was close enough to see if one of the patterns matched.
 
Dec 23, 2011 at 9:35 PM
graters gonna grate
"Heavy swords for sale. Suitable for most RPG Protagonists. Apply now!"
Join Date: Jul 2, 2008
Location: &
Posts: 1886
Age: 32
Pronouns: he/him
Bavi_H said:
Well, I just recorded from my sound card's "Stereo Mix", so I just thought they were digital to analog to digital artifacts? I didn't expect the wave in Audacity to be a bit-for-bit perfect match to what OrgMaker was outputting, but it was close enough to see if one of the patterns matched.

Actually, I'm not totally sure, but I don't think there's any analog involved until it reaches the physical speakers.
 
Jan 1, 2012 at 6:15 PM
Senior Member
"This is the greatest handgun ever made! You have to ask yourself, do I feel lucky?"
Join Date: Jul 11, 2009
Location: Texas, USA
Posts: 90
Pronouns: he/him
Wedge of Cheese said:
Actually, I'm not totally sure, but I don't think there's any analog involved until it reaches the physical speakers.
Wedge of Cheese said:
The little squiggles around where it reaches zero suggest that some sinc interpolation is going on.

In the silent parts of my recordings, it squiggles tiny amounts around zero, so I think my sound card really is recording an analog version of the signal. Either way, I now agree the larger squiggles we see before and after the descending section in that test wave may be interpoloation.

When I was browsing the DirectSound documentation it talks about setting up a primary buffer that has the main output frequency, and secondary buffers that can each have their own frequency. I suspected OrgMaker uses secondary buffers for each note. But I didn't investigate exactly what happens when OrgMaker requests a secondary buffer play at a certain frequency, but DirectSound is mixing all the secondary buffers into one primary buffer with a different main output frequency. There must be some sample rate conversion going on and maybe it's using the sinc interpolation you're talking about. This is new stuff for me.

Wedge of Cheese said:
Implementing this in my program would probably fix the thing where certain melody instruments sound shrieky and distorted (i.e. the main melody instrument in "Arctic Frolic" from TWoR).

I found your Artic Frolic here, and the melody (track 8) uses Wave-97. In OrgMaker, the last four melodic instruments (Wave-96 to Wave-99) are made of very irregular looking waveforms. (See wave-96-to-99.png or wave100-graphs.zip.) I wonder if it's only these last four instruments that sound shrieky and distorted in your Java Org Player?
 
Jan 1, 2012 at 6:48 PM
graters gonna grate
"Heavy swords for sale. Suitable for most RPG Protagonists. Apply now!"
Join Date: Jul 2, 2008
Location: &
Posts: 1886
Age: 32
Pronouns: he/him
Bavi_H said:
I found your Artic Frolic here, and the melody (track 8) uses Wave-97. In OrgMaker, the last four melodic instruments (Wave-96 to Wave-99) are made of very irregular looking waveforms. (See wave-96-to-99.png or wave100-graphs.zip.) I wonder if it's only these last four instruments that sound shrieky and distorted in your Java Org Player?

Hmm, in those images, it looks like there are several places where the waveform is rapidly alternating between a high place and a low place. Maybe discarding sample frames according to the paradigm you posted earlier would fix the screechiness. The sinc interpolation might work as well, but that would be quite a bit more computationally expensive, due to the number of Math.sin()s I'd have to do (I found when implementing your volume/pan paradigm that even a single Math.pow() per sample frame was too much for Java to handle, so I had to optimize it to only recalculate the left/right volumes of each track at every organya click, rather than every sample frame). I could make it less expensive by making a sine table at the start of the program and reading off of that, but I think that would still be more complicated than just doing the sample frame discarding.



Also, for a progress update:

Wedge of Cheese said:
Current to-do list:

-make the pi feature work as Bavi H described
-fix bug where sometimes some notes play when they shouldn't when the song loops back (this happens in "danger.org" from TWoR)
-add sinc interpolation to fix screechiness of some melody instruments
-change interpretation of volume/pan
-make the level monitor in the player app refresh more frequently so it looks smoother
-add mouse scroll-wheel support to the player app

Currently, all except the 2nd and 3rd of these are done.
 
Jan 1, 2012 at 7:05 PM
Been here way too long...
"Life begins and ends with Nu."
Join Date: Jan 4, 2008
Location: Lingerie, but also, like, fancy curtains
Posts: 3052
Slightly off topic, but could I bugger you to explain what sinc interpolation is?
 
Jan 1, 2012 at 8:09 PM
graters gonna grate
"Heavy swords for sale. Suitable for most RPG Protagonists. Apply now!"
Join Date: Jul 2, 2008
Location: &
Posts: 1886
Age: 32
Pronouns: he/him
Sinc interpolation is a special case of sinc filtering, which is a method of removing all harmonics from a sound above a certain cutoff frequency and leaving all other harmonics untouched (I'm not totally sure, but I believe harmonics exactly at the cutoff frequency have their amplitudes halved). I don't fully understand why it works, but here's how it works:

A sinc filter is a filter whose impulse response function is the normalized sinc function:
sinc(x)=...
if x=0: 1
if x!=0: sin(pi*x)/(pi*x)
which looks like this:
p111636-0-454pxsincfunction28normalized29.png


Note that, mathematically, a filter is a transformation on a function (like differentiation and integration) that has certain special properties. The impulse response function of a filter is the function that results from performing the transformation on the impulse function (an infinitely thin, infinitely tall spike at x=0, and zero everywhere else).

Given a filter with impulse response function ir(x), you can transform f(x) into g(x) in the following way:
giflatex2.png


In digital audio, a waveform consists of a bunch of discrete points, so when you "integrate", all you're really doing is multiplying the height of each point by the appropriate value in the IRF, and adding them all up.

Many filters have finite impulse response, meaning that only a finite portion of the IRF is nonzero, so you don't actually have to integrate from negative infinity to infinity, only over the nonzero portion of the IRF. The sinc function, however, has an infinite nonzero portion, so you can't truly program a computer integrate over the entire function, as that would take infinitely long. The best you can do is approximate by using some portion of the function like -10 to 10 or -100 to 100 or something like that.

Generally speaking, audio interpolation is something that must be done any time you want to play an audio sample and it involves examining the waveform between sample frames rather than on sample frames (it essentially converts the set of discrete points to a continuous function). The simplest way is to round to the nearest sample frame (nearest neighbor interpolation). The next simplest way is to play "connect the dots" with the sample frames (linear interpolation). There are others, but sinc interpolation is the theoretical ideal (though, as mentioned before, it's impossible to implement perfectly due to the need for an infinite integral) as it (theoretically) produces no aliasing (introduction of new frequencies) unlike the others, and is therefore also known as "anti-aliasing".

Sinc interpolation converts the discrete set of points in a digital audio sample to a continuous function by applying the sinc filter to the function consisting of an impulse of the appropriate height (which is technically infinite) at every sample frame.

For example, suppose the digital audio sample f(x) consisted of the following 3 sample frames:
f(0)=1
f(1)=-1
f(2)=2

The corresponding continuous function, as derived with sinc interpolation, would be:
g(x)=1*sinc(0-x) + -1*sinc(1-x) + 2*sinc(2-x)
 
Last edited by a moderator:
Jan 1, 2012 at 8:23 PM
Senior Member
"This is the greatest handgun ever made! You have to ask yourself, do I feel lucky?"
Join Date: Jul 11, 2009
Location: Texas, USA
Posts: 90
Pronouns: he/him
Wedge of Cheese said:
Hmm, in those images, it looks like there are several places where the waveform is rapidly alternating between a high place and a low place. Maybe discarding sample frames according to the paradigm you posted earlier would fix the screechiness.

Actually, I sort of simulated this idea already, it sounded a little bit better, but OrgMaker still sounds better.

The melody in Artic Folic is mostly in OrgMaker octave 4, some in octave 5. If my theories from interpeting my tests are correct, OrgMaker only uses all 256 source points of an melodic instrument wave in octaves 0 and 1. After that, each time it goes up an octave, OrgMaker discards every other source point. By octave 4 it only uses 32 of the original 256 source points. In octave 5 it only uses 16 of the original 256 source points. (I guess this is roughly filtering out high frequencies from the source wave.)

To simulate this effect in your Org Player, I modified the orgsamp.dat so that the data for Wave-97 has 32 groups of 8 identical points (to simulate 32 unique points). I made a test ORG with just the melody measures and track from Artic Frolic, and compared how it played in OrgMaker v1, your Java Org Player with original orgsamp.dat and with modified orgsamp.dat.


Worst to best timbre:

Java Org Player with original orgsamp.dat.
Java Org Player with modified orgsamp.dat.
OrgMaker with sample rate conversion quality Good (Standard).
OrgMaker with sample rate conversion quality Improved or Best. (Timbre sounds better, but pitches sound slightly out of tune.)

What exactly does the sample rate conversion quality setting do? This is what I've found so far: Policy for Sample Rate Conversion of Audio Streams says "The slider shown in the Advanced Audio Properties dialog assigns the settings Good through Best to linear interpolation, multipoint interpolation, and high-end multipoint interpolation, respectively." Types of Sample Rate Conversion describes those interpolations slightly more, and also mentions Add/Drop (also known as truncation or nearest neighbor) is used if system constraints prevent a higher quailty conversion. I'm not sure what it all means, maybe it's useful to you.

_____

Lace said:
Slightly off topic, but could I bugger you to explain what sinc interpolation is?

Wedge of Cheese's answer has more details, but so far I've just imagined it as some magic I don't understand that happens when you have a wave that plays at one playback rate, and you want to convert it to play at a different playback rate. I think it has something to do with sample rate converter (SRC) algorithms and ideal low-pass filter.
 
Jan 1, 2012 at 9:52 PM
graters gonna grate
"Heavy swords for sale. Suitable for most RPG Protagonists. Apply now!"
Join Date: Jul 2, 2008
Location: &
Posts: 1886
Age: 32
Pronouns: he/him
Bavi_H said:
Worst to best timbre:

Java Org Player with original orgsamp.dat.
Java Org Player with modified orgsamp.dat.
OrgMaker with sample rate conversion quality Good (Standard).
OrgMaker with sample rate conversion quality Improved or Best. (Timbre sounds better, but pitches sound slightly out of tune.)

What exactly does the sample rate conversion quality setting do? This is what I've found so far: Policy for Sample Rate Conversion of Audio Streams says "The slider shown in the Advanced Audio Properties dialog assigns the settings Good through Best to linear interpolation, multipoint interpolation, and high-end multipoint interpolation, respectively." Types of Sample Rate Conversion describes those interpolations slightly more, and also mentions Add/Drop (also known as truncation or nearest neighbor) is used if system constraints prevent a higher quailty conversion. I'm not sure what it all means, maybe it's useful to you.

I think I'd be able to do #3 on that list. From what you said, it sounds like #3 is linear interpolation, and #4 is sinc interpolation.


edit: also, I found a typo on your online notes:

0 every source point is used 4 times 256 * 4 = 2048 points
1 every source point is used 2 times 256 * 2 = 512 points
2 every other source point is used 2 times 256 points
3 every 4th source point is used 2 times 256 / 2 = 128 points
4 every 8th source point is used 2 times 256 / 4 = 64 points
5 every 16th source point is used 2 times 256 / 8 = 32 points
6 every 32nd source point is used 2 times 256 / 16 = 16 points
7 every 64th source point is used 2 times 256 / 32 = 8 points
The first one should be 1024 points, not 2048.
 
Jan 1, 2012 at 10:59 PM
graters gonna grate
"Heavy swords for sale. Suitable for most RPG Protagonists. Apply now!"
Join Date: Jul 2, 2008
Location: &
Posts: 1886
Age: 32
Pronouns: he/him
Finished! First post updated.

This will probably be on the tribute site soon as well.
 
Jan 2, 2012 at 3:50 AM
Senior Member
"This is the greatest handgun ever made! You have to ask yourself, do I feel lucky?"
Join Date: Jul 11, 2009
Location: Texas, USA
Posts: 90
Pronouns: he/him
Wedge of Cheese said:
The first one should be 1024 points, not 2048.
Thanks, fixed.
 
Jun 21, 2014 at 11:56 PM
Neophyte Member
"Fresh from the Bakery"
Join Date: Oct 31, 2011
Location:
Posts: 2
I suggest you take a look at the resampler.[ch] I use in modplay library, which implements multiple resampling methods for PCM samples which play at configurable sample rates.

It includes zero-order-hold, which is basically no interpolation whatsoever; Band-limited step synthesis, which is like a bandwidth limited zero order hold, where upsampling is not interpolated, and downsampling is effectively sinc resampled; linear and cubic, which everyone knows; windowed sinc resampling, which interpolates when upsampling and filters when downsampling, which is closer to the "best" mode of DirectSound, but doesn't have the pitch accuracy issues that Windows XP had.

The sinc interpolation mode also uses a separate window lookup table, because when downsampling, the scope of the sinc pulse is scaled down, but the window remains the same size.

It is initialized once on program startup to build the lookup tables, then instances are created per input channel. Typical usage, each instance is first configured with the input to output ratio for a run of samples, then a loop runs where the instance is pumped with input samples whenever it has room for them, and samples are pulled out one at a time. As you can see, it's designed for low latency.

I also have a liborganya fork that uses purely band limited synthesis, based on Blargg's blip_buf.c, but that's a little bit different, since it requires the caller to feed it timestamped delta samples, and only as far ahead as there is buffer space. And that may make the high pitched samples sound correct, but the lower pitched ones end up having more high frequency content not present when playing with the original player. This may or may not be desirable. Oh, right, and it doesn't handle volume ramping, so large volume changes tend to cause audible clicks. Maybe I'll fix that some day, if someone else doesn't fork it again from me and fix it for everyone.
 
Jun 22, 2014 at 3:47 AM
Junior Member
"It's dangerous to go alone!"
Join Date: May 26, 2014
Location: on the Internet
Posts: 43
kode54 said:
Oh, right, and it doesn't handle volume ramping, so large volume changes tend to cause audible clicks. Maybe I'll fix that some day, if someone else doesn't fork it again from me and fix it for everyone.
I don't think original Organya did either.

In other news, I ported OrgPlayer to ActionScript3 because the Java replayer has terribad audio loop and I don't know how to Java(also because it's an excuse to have another replayer ported to and usable in flash).
Should I get off my lazy bumarse, I will clean it up, add a few things and maybe port it to C, where it's actually useful.

Usable player here. Just click RAW to download.
 
Jun 26, 2014 at 3:38 AM
Senior Member
"This is the greatest handgun ever made! You have to ask yourself, do I feel lucky?"
Join Date: Jul 11, 2009
Location: Texas, USA
Posts: 90
Pronouns: he/him
Jun 30, 2014 at 2:04 PM
Junior Member
"It's dangerous to go alone!"
Join Date: May 26, 2014
Location: on the Internet
Posts: 43
Maybe the SOTP [sic] button should say PAUSE?
Maybe.

Edit:
* Separated all the player buttons in interface.
* Added ugly playback indicator, in place of the overlapping play/pause buttons.
* Made the interface overall uglier.
* Added funky play bug/feature(click play multiple times).

Edit2:
* Fixed a looping issue.
* Made the code somewhat messier than it already was.
* Added a saving function. You can now save tunes you can't even edit :D.

Edit3:
I'm thinken of sacrificing funkyplay in favour of having hanging drum notes on pause, a-la OrgMaker/Cave Story. :<
Decisions, decisions...
What do you guys think?
 
Aug 6, 2014 at 8:25 PM
Um... Chosen One? Yeah that'll work. : P
"..."
Join Date: Aug 3, 2014
Location: worm hole
Posts: 363
Age: 23
Pronouns: she/her
I will use this one day.

One day.
Lace said:
This is sorta random, but could you port this to the far lesser language of C?
Or make a dll?


Haven't looked at the code yet, but I'm sure it'll be interesting.
Good work bud.
ew C.

I'd recommend upgrading to C++, C's really only for people who want to use the most outdated language possible for the sakes of being "2cul4skul"

Or is C good, idk.
I've heard it's not that good compared to every newer language, but I might talk to the wrong people on these things.
 
Back
Top