Upload
beverley-lewis
View
215
Download
0
Embed Size (px)
Citation preview
1
Sound in Java
Summary: Sound API Basics MIDI
JavaSound- Part of the UIT
User Interface Toolkit
2
3
MIDI in JavaSound Data is a MIDI file is a series
of commands that defines a piece of music
Up to 16 MIDI channels are available (each instrument uses one channel)
A MIDI Synthesizer reproduces(synthesizes) sounds in response to MIDI commands H/W part of the sound card S/W as in JavaSound
A sequencer is a device that processes a MIDI sequence in order to play it on a synthesizer, or possible to edit it. H/W or S/W
A device conforming to the General MIDI spec. must provide:
A min. of 128 preset instruments + 47 percussive sounds
A min. of 16 simultaneous timbres (instruments)
A min. of 24 simultaneous voices, where each voice is a note of given velocity (loudness) for any of the available instruments and percussive sounds
16 midi channels, where each channel is polyphonic(can play multiple simultaneous voices). Percussive sounds are always on channel 10
4
Midi Note Numbers
The Note Number ranges from 0-127 60 = middle C Number DIV 12 is the octave 91 DIV 12 or octave number 7 127 DIV 12 or 10 octaves in all
5
Note Number to Class
Number MOD 12 is the note class Note Name Note Class
C 0C# 1D 2
D# 3E 4F 5
F# 6G 7
G# 8A 9
A# 10B 11
6
Whole Note Names CDEFGABC Whole Note Classes Wnc[]={0,2,4,5,7,9,
11}
Note Name Note ClassC 0
C# 1D 2
D# 3E 4F 5
F# 6G 7
G# 8A 9
A# 10B 11
7
Note Class
Octave-NN matrixOctave Note Numbers # C C# D D# E F F# G G# A A# B
0 0 1 2 3 4 5 6 7 8 9 10 111 12 13 14 15 16 17 18 19 20 21 22 232 24 25 26 27 28 29 30 31 32 33 34 353 36 37 38 39 40 41 42 43 44 45 46 474 48 49 50 51 52 53 54 55 56 57 58 595 60 61 62 63 64 65 66 67 68 69 70 716 72 73 74 75 76 77 78 79 80 81 82 837 84 85 86 87 88 89 90 91 92 93 94 958 96 97 98 99 100 101 102 103 104 105 106 1079 108 109 110 111 112 113 114 115 116 117 118 119
10 120 121 122 123 124 125 126 127
8
Note Number to Frequency
public static double getMidiFrequency(int midiNoteNumber){
return 440. * Math.pow(2,((midiNoteNumber-69.)/12.));
}
( 69) /12440*2 nnf
9
MIDI Resources in JavaSound
Sequencer Synthesizer
MidiDevice
Declares basic operations for a MIDI device. Inner class, MidDevice.Info can be used for specifying a device
A sequencer object can play a sequence, which you can construct from a MIDI file
A synthesizer object encapsumates a h/w or s/w MIDI synthesizer
Declares operations specific to a synthesizer
Declares operations specific to a sequencer. Innerclass Sequencer.SyncMode used for synchronizing with another device
10
Playing a MIDI fileTo play a MIDI file, you don’t need to access a synthesizer
directly. All you need is a Sequencer reference and an object encapsulating the sequence that you want to play.
Steps:1. sequencer = MidiSystem.getSequencer();
// Get a sequencer
2. sequencer.open(); 3. sequence = MidiSystem.getSequence(midiFile)
// Encapsulate the midi src (file here; URL possible) in a sequence obj.
4. sequencer.setSequence(sequence); // Hand the sequence over to the sequencer
5. sequencer.start();// Play it. Stop it: sequencer.stop()
11
12
Java Sound Preliminaries
File Formats Supported .au or .snd : usually
stores 8-bit -law encoded samples, but can also store 8 or 16 bit linear samples
.aif : usually stores 8 or 16 bit linear encoded samples
.wav :Can store 8 or 16 bit samples using linear or -law encoded samples
.midi : follows the midi data format
Note: The file header indicates the actual format
Frames and Frame Rates Sample Frame
Stores all the samples taken at an instant of time
# of bytes in a frame = # of bytes in a sample X number of channels
Frame Rate The number of frames per
second of sound In most cases frame rate is
same as sample rate In compressed sound, the
frame rate will be less than sample rate.
13
Simple Sound Outputimport java.applet.*;
import javax.swing.*;
import java.awt.event.*;
public class PlayIt extends JApplet
{
AudioClip clip; // The sound clip
JButton button;
final String play = "PLAY";
final String stop = "STOP";
public void init()
{
// Get the sound clip
String fileName = getParameter("clip");
// Get the file name
clip =
getAudioClip(getDocumentBase(),fileName);
// Create the clip
// Rest of the applet initialization...
button = new JButton(play);
button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
if(e.getActionCommand().equals(play))
{
clip.loop();
button.setText(stop);
}
else
{
clip.stop();
button.setText(play);
}
}
}
);
getContentPane().add(button);
}
<APPLET CODE =“PlayIt.class” CODEBASE = “.” WIDTH = 300 Height = 50 clip = “myClip.wav” >
</APPLET>
Playit.html
PlayIt.java
14
Sound in Applications
Similar to an Applet The Applet class defines a static method,
newAudioClip()that retrieves an audio clip from a URL and returns a reference type AudioClip that encapsulates the audio clip. This method being static, you don’t have to have
an applet object to call it. It can be called from an application as well, like so:AudioClip clip = Applet.newAudioClip(URL location)
Take a look at example PlaySounds.java in the examples directory
15
Java Sound APISystem Resources Audio Line: Any resource
that is a source or destination of sampled sound data A line can encapsulate
several channels Example: input/output
ports on the sound card Lines have controls (gain
and pan control) Mixer: Receives input
from one or more source data lines and outputs the result of combining the input to an output line called a target data line
Other Sound Sources A file or more generally a
URL
Terminology: A source data line is a
source for a mixer, not a source for you; you write to it
A target data line is the output from the mixer; your read from it
MIXERSound i/p
Sound i/p
Sound i/p
Sound o/p
Sound o/p
Target Data LinesSource Data Lines
16
Java Sound API (…contd)Packages: javax.sound.sampled javax.sound.midi javax.sound.sampled.spi javax.sound.sampled.mid
i
The AudioSystem class Establish whether a
particular resource is available
Get a ref. to the object that encapsulates the resource
Call methods to operate the resource
AudioStreamInput class Represents a stream that
is a source of sampled sound data with a specific format
You can create an AudioStreamInput object from a local sound file, from another input stream or a URL
You can Read data from it Write its contents to an
output stream Convert its format
17
Sampled Sound Interfaces
TargetDataLineSomething you read from.
Data keeps comingUse it or loose it!
Mixer DataLinePort
(mic, dataline, etc)
SourceDataLine
Line(info on everything)
Clip (not streaming)Audio in memory
18
Resource Descriptor Classes
Mixer.Info DataLine.Info Port.Info
Line.Info
The Line, DataLine, Mixer and Port interface definitions each include an inner class with the name Info. Objects of these class types encapsulate data specifying an object of the corresponding type
Specifies a Line object by its Class
Specifies a Mixer object by its name, vendor version and description
Specifies a DataLine by the audio formats to be supported, the buffer size limits, and the Class of the data line
Specifies a Port object by its Class, its name, and whether it is a source or target line
19
Why Descriptor Class?In order to answer that question, we have to look at the
steps involved in playing audio:1. Create an instance of a Line that specifies the format
of the sound data you wish to play (use descriptor class). Not all formats will be supported.
2. Get a reference to a line (a DataLine, Port, Mixer or Clip) that supports this format
1. May check if supported before requesting reference
3. Create an Audio Stream that encapsulates the sound data (file, URL, another stream)
1. Extract the format from the Audio Stream
4. Tie the source of the sound data to the reference (line) that will play it. I.e., open the source
5. Play it; loop; goto; quit.
20
Playing a Clip vs. StreamAudioInputStream source =
AudioSystem.getAudioInputStream(file);
// Step 3.
DataLine.Info clipInfo = new DataLine.Info(Clip.class, source.getFormat());
// Step 1.
if(AudioSystem.isLineSupported(clipInfo))
{
Clip newClip = (Clip)AudioSystem.getLine(clipInfo);
// Step 2.
newClip.open(source);// Step 4.
}
clip.loop(clip.LOOP_CONTINUOUSLY); // loop
clip.stop(); // stop
clip.setFramePosition(0);
Clip.close();
AudioInputStream newSource = AudioSystem.getAudioInputStream(file);
// Step 3.AudioFormat format = newSource.getFormat(); DataLine.Info sourceInfo = new
DataLine.Info(SourceDataLine.class, format); // Step 1.
if(AudioSystem.isLineSupported(sourceInfo)){ srcLine =
(SourceDataLine)AudioSystem.getLine(sourceInfo); // Step 2.
bufferSize = (int)(format.getFrameSize()*format.getFrameRate()/2.0f);
soundData = new byte[bufferSize]; srcLine.open(format, bufferSize); //4.}while(playing){ byteCount = source.read(soundData, 0,
soundData.length); // Read the stream if(byteCount == -1) { sourceLine.drain(); // rest of buffer playing = false; break; } sourceLine.write(soundData,0, byteCount);
// Write the array to the line}