Could you write this sound applet?  
Author Message
Chris





PostPosted: 2004-11-20 22:27:00 Top

java-programmer, Could you write this sound applet? As a start, consider this simple QBASIC program that generates random
frequencies:

10 frequency = 40 + 400 * RND
20 SOUND frequency, 7
30 GOTO 10

That's fine - except that it plays over the PC speaker - the one that's
just there for the happy beep - and not through the sound card and
proper speakers. You can't control volume, either.

I wonder if anyone would be kind enough to translate the above three
line program into a Java applet. I would like to see whether it looks
simple enough for me to cope with.

If it looks as if I could cope with Java, I would then learn it, and try
to program a way of generating sounds from a mathematical sequence or
formula.
--
Chris
 
Chris Smith





PostPosted: 2004-11-21 0:39:00 Top

java-programmer >> Could you write this sound applet? Chris <nospam@[127.0.0.1]> wrote:
> 10 frequency = 40 + 400 * RND
> 20 SOUND frequency, 7
> 30 GOTO 10

> I wonder if anyone would be kind enough to translate the above three
> line program into a Java applet. I would like to see whether it looks
> simple enough for me to cope with.

You've picked a task that doesn't have a simple Java API. If you wanted
to play a sound file, or something along those lines, it would be much
easier. Here's a shot at your task, though. I've created AU-format
data (a simple file format that was convenient) and just played that.
You should be able to make this work by producing raw sound data as
well, but I didn't think about it initially.

Just know that this kind of low-level task isn't representative of most
Java programming. By the way, I don't know QBASIC's sound functions, so
I've assumed that "7" is the length of the tone. Feel free to correct
my variables below.

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;

import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.SourceDataLine;

public class Test
{
public static void main(String[] args) throws Exception
{
double freq = 40 + (400 * Math.random()); // Hz
double volume = 1.0; // range [0, 1]
double length = 7.0; // seconds
int sample = 11025; // samples / second

int nsamples = (int) (sample * length);

ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
DataOutputStream out = new DataOutputStream(byteOut);

out.writeInt(0x2e736e64);
out.writeInt(24);
out.writeInt(nsamples);
out.writeInt(2);
out.writeInt(11025);
out.writeInt(1);

/* Sample data is produced by a sin function */
double fmultiplier = freq * 2 * Math.PI / sample;
double vmultiplier = volume * 127;
for (int n = 0; n < nsamples; n++)
{
out.writeByte((int) (
vmultiplier * Math.sin(n * fmultiplier)));
}

out.flush();

AudioInputStream in = AudioSystem.getAudioInputStream(
new ByteArrayInputStream(byteOut.toByteArray()));

SourceDataLine line = AudioSystem.getSourceDataLine(
in.getFormat());
line.open(in.getFormat());
line.start();
byte[] buf = new byte[16384];
int len;
while ((len = in.read(buf)) != -1)
{
line.write(buf, 0, len);
}

line.drain();
line.close();
}
}

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
Chris Smith





PostPosted: 2004-11-21 0:51:00 Top

java-programmer >> Could you write this sound applet? Chris Smith <email***@***.com> wrote:
> > I wonder if anyone would be kind enough to translate the above three
> > line program into a Java applet.

And, silly me, I posted an application instead. The code from inside
main can be moved into any appropriate place in an applet to accomplish
the same thing. However, there is a permission needed to play audio
data, and I don't know if applets get it by default. You may need to
sign the applet and request permission from the user.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
 
Chris Smith





PostPosted: 2004-11-21 3:08:00 Top

java-programmer >> Could you write this sound applet? Chris Smith <email***@***.com> wrote:
> You should be able to make this work by producing raw sound data as
> well, but I didn't think about it initially.

Here's a function to do the same thing without producing a file format
first. This is really far better code than what I posted the first
time, and I'm donating it to the public domain. It can be called from
any context (application or applet), but it needs permission to play
sounds. It's not specified anywhere that applets wouldn't be granted
this permission, but that's really up to the web browser. So, you may
need to sign an applet to get the appropriate AudioPermission ("play").

/*
* Plays a pure tone with a constant frequency.
*
* @param freq Frequency, in Hz
* @param volume Relative volume, on a scale from 0.0 to 1.0
* @param length Length of tone, in seconds
* @param sample Sampling frequency, in Hz. Your sound hardware
* must be capable of playing sounds at this sampling
* frequency. It is recommended that you use a value
* of 8000, 11025, 22050, 44100, 48000, 96000, or
* 192400.
*
* @throws LineUnavailableException
* Your sound hardware is incapable of playing the sound.
* Either the system does not have sound hardware installed,
* or the sampling frequency is not supported.
*/
public static void playTone(
double freq, double volume, double length, float sample)
throws LineUnavailableException
{
int nsamples = (int) (sample * length);

AudioFormat format = new AudioFormat(sample, 8, 1, true, true);
SourceDataLine line = AudioSystem.getSourceDataLine(format);

byte[] buf = new byte[16384];
int bufi = 0;

line.open(format);
line.start();

/* Sample data is produced by a sin function */
double fmultiplier = freq * 2 * Math.PI / sample;
double vmultiplier = volume * 127;
for (int n = 0; n < nsamples; n++)
{
int val = (int) (vmultiplier * Math.sin(n * fmultiplier));
buf[bufi++] = (byte) val;
if (bufi == buf.length)
{
line.write(buf, 0, bufi);
bufi = 0;
}
}

if (bufi > 0) line.write(buf, 0, bufi);
line.drain();
line.close();
}


--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
 
Chris





PostPosted: 2004-11-22 0:51:00 Top

java-programmer >> Could you write this sound applet? In article <email***@***.com>, Chris Smith
<email***@***.com> writes
>Chris Smith <email***@***.com> wrote:

>> You should be able to make this work by producing raw sound data as
>> well, but I didn't think about it initially.

>Here's a function to do the same thing without producing a file format
>first. This is really far better code than what I posted the first
>time, and I'm donating it to the public domain. It can be called from
>any context (application or applet), but it needs permission to play
>sounds. It's not specified anywhere that applets wouldn't be granted
>this permission, but that's really up to the web browser. So, you may
>need to sign an applet to get the appropriate AudioPermission ("play").

Chris - first let me apologise for my tardy response. I had to divert
to sort out a hardware problem.

Next - I would like to express my sincere appreciation for the trouble
you have gone to. I am overwhelmed by the amount of work you must have
put into answering my question.

However ... I'm slightly nonplussed, too!
You are so far above my level that I hardly know what to say or ask.
Remember that I'm just a lowly QBASIC programmer.
And the program I wrote was a mere three lines!

I'll try a scatter-gun questioning approach - in case one of my
questions comes close to being relevant. Only answer if you have time -
you have been kind enough to do a lot already.

How can your function be used?
Could you put it in an applet on a website?
Does it mean I could write a program like the following:
Function frequency1, duration1, volume1
Function frequency2, duration2, volume2
Function frequency3, duration3, volume3?

If so - that would be fantastic - because then I could start feeding
values to the function from a formula. For instance, I could see what a
parabola sounds like!

Or feed the digits of pi into the function to generate sounds with
random frequency, duration, and volume.

Is that the sort of thing that could be done with your function?
--
Chris
 
 
Andrew Thompson





PostPosted: 2004-11-22 1:28:00 Top

java-programmer >> Could you write this sound applet? On Sun, 21 Nov 2004 16:51:04 +0000, Chris wrote:

> How can your function be used?
> Could you put it in an applet on a website?

Since Shris has done most of the hard work already, I'll venture
an answer to this one.

Put the following lines before Chris' playTone method..

<code>
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import javax.sound.sampled.*;

public class ToneApplet extends Applet implements ActionListener {

Button tone;

public void init() {
setLayout(new BorderLayout());
tone = new Button("Play");
add(tone, BorderLayout.CENTER);
tone.addActionListener(this);
}

public void actionPerformed(ActionEvent ae) {
try {
playTone(441.0, 0.5, 2, 48000.0f) ;
} catch(LineUnavailableException lue) {
lue.printStackTrace();
tone.setEnabled(false);
}
}
</code>

..and this one after..

<code>
}
<code>

> Does it mean I could write a program like the following:
> Function frequency1, duration1, volume1
> Function frequency2, duration2, volume2
> Function frequency3, duration3, volume3?

Play with the source, 'Luke'.

Note also that playing a sound is allowed in an unsigned applet
(I suspected as much, but wanted to check it* before commenting).
The only problem with sound comes when trying to *record* the sound
that is going through the sytem's audio lines (eavesdropping).

* IE 6 & Moz. 1.7.2 running Java 1.5.0 beta.

HTH

--
Andrew Thompson
http://www.PhySci.org/codes/ Web & IT Help
http://www.PhySci.org/ Open-source software suite
http://www.1point1C.org/ Science & Technology
http://www.LensEscapes.com/ Images that escape the mundane
 
 
Chris Smith





PostPosted: 2004-11-22 1:52:00 Top

java-programmer >> Could you write this sound applet? Chris <nospam@[127.0.0.1]> wrote:
> Next - I would like to express my sincere appreciation for the trouble
> you have gone to. I am overwhelmed by the amount of work you must have
> put into answering my question.

Not a problem. I was happy for an opportunity to figure out some of the
basics of the sound APIs. I'm sure the knowledge I gained will come in
handy at some point. I'm playing around this morning with modifying
wave forms, and I've got rough approximations of several basic vowel
sounds working. This is fun!

> However ... I'm slightly nonplussed, too!
> You are so far above my level that I hardly know what to say or ask.
> Remember that I'm just a lowly QBASIC programmer.
> And the program I wrote was a mere three lines!

I told you, in my first response, that you've chosen a task that sort of
falls between the cracks of Java APIs. The complexity of this task is a
coincidence; it's not indicative of the Java API in general. The code
is missing from the standard API because modern applications very rarely
produce constant pure tones like that. Playing a sound clip that you've
included with your applet is actually much easier, especially from an
applet.

> How can your function be used?

Just include it in your code, and call it.

> Could you put it in an applet on a website?

Yes. Whether you need to worry about security or not, though, is an
open question. Applets run under very severe security restrictions.
Since there's no official answer to this question, you'd need to write
the applet, and then just test it in various browsers.

> Does it mean I could write a program like the following:
> Function frequency1, duration1, volume1
> Function frequency2, duration2, volume2
> Function frequency3, duration3, volume3?

It would look something like this:

playTone(frequency1, volume1, duration1, 48000);
playTone(frequency2, volume2, duration2, 48000);
playTone(frequency3, volume3, duration3, 48000);

You would then include my function in the same class as the code that
calls it. You could also put the function in a different class (for
example, called SoundUtil), and then write this instead:

SoundUtil.playTone(frequency1, volume1, duration1, 48000);
SoundUtil.playTone(frequency2, volume2, duration2, 48000);
SoundUtil.playTone(frequency3, volume3, duration3, 48000);

The 48000 is a sampling rate; 48000 is generally used for professional
digital audio, and some lesser rate is probably sufficient for your
needs, but there's not a lot of cost to using the higher rate for
generated sound (if you were saving the sound as a file, the higher
sampling rate would result in a larger file).

> If so - that would be fantastic - because then I could start feeding
> values to the function from a formula. For instance, I could see what a
> parabola sounds like!
>
> Or feed the digits of pi into the function to generate sounds with
> random frequency, duration, and volume.
>
> Is that the sort of thing that could be done with your function?

Yes, but it sounds rather annoying! :)

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
 
Chris Smith





PostPosted: 2004-11-22 1:56:00 Top

java-programmer >> Could you write this sound applet? Andrew Thompson <email***@***.com> wrote:
> Note also that playing a sound is allowed in an unsigned applet
> (I suspected as much, but wanted to check it* before commenting).
> The only problem with sound comes when trying to *record* the sound
> that is going through the sytem's audio lines (eavesdropping).

Thanks. I was hoping that was the case, but I didn't want to promise
anything.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
 
Chris





PostPosted: 2004-11-22 14:15:00 Top

java-programmer >> Could you write this sound applet? In article <email***@***.com>, Chris Smith
<email***@***.com> writes
>Chris <nospam@[127.0.0.1]> wrote:
>> Next - I would like to express my sincere appreciation for the trouble
>> you have gone to. I am overwhelmed by the amount of work you must have
>> put into answering my question.

>Not a problem. I was happy for an opportunity to figure out some of the
>basics of the sound APIs. I'm sure the knowledge I gained will come in
>handy at some point. I'm playing around this morning with modifying
>wave forms, and I've got rough approximations of several basic vowel
>sounds working. This is fun!

Chris - you have now convinced me that it's worth my learning Java.
Well ... that should keep me out of mischief for a few years!
I have got the book "SAMS Teach Yourself Java 1.2 in 21 Days", which is
dated 1998. Is that likely to be OK - or is it too old?
--
Chris
 
 
Andrew Thompson





PostPosted: 2004-11-22 14:47:00 Top

java-programmer >> Could you write this sound applet? On Mon, 22 Nov 2004 06:15:05 +0000, Chris wrote:

> I have got the book "SAMS Teach Yourself Java 1.2 in 21 Days", which is
> dated 1998. Is that likely to be OK - or is it too old?

I am unfamiliar with that particular tome, but if it is good for
the basic principles of Java, you might flesh it out with lots
of reference to the Java API docs and Sun's tutorials (both of
which are downloadable for local browsing).

--
Andrew Thompson
http://www.PhySci.org/codes/ Web & IT Help
http://www.PhySci.org/ Open-source software suite
http://www.1point1C.org/ Science & Technology
http://www.LensEscapes.com/ Images that escape the mundane