📄 toneplayer.java
字号:
if (sequence[i+1] < 2){
reportErr(9);
}
note = sequence[i+2];
if (!(note == SILENCE || note >= 0)){
reportErr(11);
}
break;
case SET_VOLUME:
if (sequence[i+1] < 0 || sequence[i+1] > 100){
reportErr(10);
}
len += 2;
break;
case PLAY_BLOCK:
if (blockEnds.get(new Integer(sequence[i+1])) == null){
reportErr(2);
}
tmp = ((Integer)(blockEnds.get(new Integer(sequence[i+1])))).intValue();
if (inBlock) {
thisBlockEnd += tmp;
} else {
len += tmp;
}
break;
case VERSION:
case TEMPO:
case RESOLUTION:
reportErr(12);
break;
default:
// SILENCE or normal tone
if (inBlock) {
thisBlockEnd += 2;
} else {
len += 2;
}
} // switch
} // end of for(i)
if (inBlock) {
reportErr(1);
}
// valid tone seq
toneSeq = new int[len];
curTime = 0;
p = 0;
i = startseq;
int mul = 1;
while (i < sequence.length) {
note = sequence[i];
switch (note) {
case BLOCK_START: // blk definition, start
do {
i += 2;
} while (sequence[i] != BLOCK_END);
break;
case PLAY_BLOCK: // play_blk
sp.push(new Integer(i+2));
i = ((Integer)blockStarts.get(new Integer(sequence[i+1]))).intValue() + 2;
continue;
case BLOCK_END: // end playing blk
i = ((Integer)(sp.pop())).intValue();
continue;
case SET_VOLUME:
// 0 <= sequence[i+1] <= 100
toneSeq[p++] = SET_VOLUME;
toneSeq[p++] = (sequence[i+1] & 0x7f);
break;
case REPEAT:
// 2 <= sequence[i+1] <= 127
mul = sequence[i+1];
break;
default: // regular tone or SILENCE
toneSeq[p++] = sequence[i];
// dur as milliseconds
toneSeq[p++] += (sequence[i+1]&0x7f) * mul * 240000 / frac;
curTime += toneSeq[p-1];
mul = 1;
} // switch
i += 2;
} // while
} catch (IllegalArgumentException ex) {
throw ex;
} catch (Exception ex) {
throw new IllegalArgumentException(ex.getMessage());
}
seqChanged = true;
}
private void reportErr(int code) {
throw new IllegalArgumentException("bad tone param: err code " + code);
}
/**
* ==========================
* Methods for VolumeControl.
* =========================
*/
/**
* The worker method to actually obtain the control.
*
* @param vol the volume level to be set.
* @return the actual level has been set.
*/
protected int doSetLevel(int vol) {
if(clip.isControlSupported(FloatControl.Type.VOLUME)){
((FloatControl)clip.getControl(FloatControl.Type.VOLUME)).setValue((float)vol/100);
return vol;
}else{
if(clip.isControlSupported(BooleanControl.Type.MUTE)){
if(vol<=0){
((BooleanControl)clip.getControl(BooleanControl.Type.MUTE)).setValue(true);
}else if(vol>0){
((BooleanControl)clip.getControl(BooleanControl.Type.MUTE)).setValue(false);
}
}
return (int)(clip.getLevel()*100);
}
}
private void harmonics(int voices, double second, double third, double fourth, double fifth)
{
int k;
double max = 0.0;
for (k = 0; k < 361; ++k)
{
harmwave[k] =
( 1.0 * Math.sin (k * 2. * Math.PI / 360.) +
second * Math.sin (k * 4. * Math.PI / 360.) +
third * Math.sin (k * 6. * Math.PI / 360.) +
fourth * Math.sin (k * 8. * Math.PI / 360.) +
fifth * Math.sin (k * 10. * Math.PI / 360.) );
if (harmwave[k] > max){
max = harmwave[k];
}else if (-harmwave[k] > max){
max = -harmwave[k];
}
// for the milliwatt tone (single note!)
//sinewave[k] = 0.707 * Math.sin (k * 2. * Math.PI / 360.);
}
// allow up to number_of_notes simultaneous notes with harmwave[]
for (k = 0; k < 361; ++k){
//harmwave[k] *= ((0.707/voices)/max); // eg. 0.35 for 2 voices
harmwave[k] *= ((0.707/voices)/max);
}
}
private void test(){
for (int tries = 0; tries < 2; ++tries)
{
// CAF: try a few, at different rates
pcm = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
rate, sampleSizeInBits, channels,
frameSize, rate, bigendian);
DataLine.Info info = new DataLine.Info(
Clip.class,
pcm); // no buffer size -- will that be OK
try
{
clip = (Clip) AudioSystem.getLine(info);
//System.out.println("Audio DataLine started");
// hack to work around JavaSound bug 4515126.
byte [] sampleTest = new byte[2];
sampleTest[0] = 0;
sampleTest[1] = 1;
clip.open(pcm, sampleTest, 0, sampleTest.length);
clip.close();
if (sampleTest[1] == 0) // byte swapping occured in JavaSound
{
bigendian = ! bigendian;
System.out.println("Bigendian=" + bigendian + " (swapped after test)");
continue; // try a second time
}
break;
}
catch (Exception ex)
{
System.out.println("Audio exception: " + ex);
clip = null;
}
}
}
private void toneInitSeq(){
test();
int len=rate*curTime/1000;
if(samples==null||samples.length<(len<<1)){
samples=null;
samples=new byte[len<<1];
}
len=0;
for(int i=0; i<toneSeq.length; i+=2){
int lgt=rate*toneSeq[i+1]/1000;
double volt=0;
double deg;
double degm;
int degi;
for(int j=0; j<lgt; ++j){
if(toneSeq[i]>0){
deg = ((toneSeq[i]/127.0)*80+80) * j;
degi = (int) deg;
degm = deg - (double)degi;
/*
volt += sinewave[degi%360] + // linear interpolate
degm * (sinewave[(degi%360)+1] - sinewave[degi%360]);
*/
volt += harmwave[degi%360] + // linear interpolate
degm * (harmwave[(degi%360)+1] - harmwave[degi%360]);
short val = (short)(volt * 32767.);
if(bigendian){
samples[len+(j<<1)]=(byte)(val>>8);
samples[len+(j<<1)+1]=(byte)(val&0xff);
}else{
samples[len+(j<<1)+1]=(byte)(val>>8);
samples[len+(j<<1)]=(byte)(val&0xff);
}
}else{
samples[len+(j<<1)]=0;
samples[len+(j<<1)+1]=0;
}
}
len+=(lgt<<1);
}
try{
ByteArrayInputStream bis=new ByteArrayInputStream(samples);
AudioInputStream ais=new AudioInputStream(bis,pcm,samples.length/(sampleSizeInBits>>3));
clip.open(ais);
}catch(Exception e){
e.printStackTrace();
}
}
public void run(){
try{
if(clip!=null&&clip.isOpen()){
clip.start();
while (clip.isActive() && thread != null) {
try {
Thread.sleep(300);
}catch (Exception e) {
break;
}
}
this.sendEvent(PlayerListener.END_OF_MEDIA,null);
}
if(thread!=null){
thread.interrupt();
thread=null;
}
}catch(Exception e){
e.printStackTrace();
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -