gpt4 book ai didi

Java midi播放质量不一致

转载 作者:行者123 更新时间:2023-12-02 07:49:09 24 4
gpt4 key购买 nike

我最近在我正在开发的游戏中玩 midis 时遇到了一个奇怪的错误。我认为我的 midi 代码工作正常,因为它过去可以播放 midi 而不会听起来很奇怪。现在,每当它播放 midis 时,它们听起来都尖细、有回声且响亮。

我已经很长时间没有碰过我的 midi 播放器代码了,所以我想知道最近的 Java 更新是否可能暴露了我的代码中一直存在的错误。或者也许我的 Java 版本中存在某种我不知道的 midi bug?

每当我在游戏之外播放 midis 时,它们听起来都很好。

我正在运行 Java 6,更新 31,内部版本 1.6.0_31-b05。这是重现该问题的 SSCCE(至少在我的 JVM 上重现):

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import javax.sound.midi.*;
import java.net.URL;

public class MidiSSCCE extends JFrame
{

public MidiSSCCE()
{
super("Sound problem SSCCE");
this.setSize(200,100);

// instantiate main window panel

JPanel screenP = new SSCCEPanel(this);
this.add(screenP);

// finishing touches on Game window

this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);

System.out.println("Game Window successfully created!!!");
}

public static void main(String[] args)
{
MidiSSCCE gui = new MidiSSCCE();
}
}


/**
* SSCCEPanel is the JPanel that manages the example's timer, painting, and logic.
**/

class SSCCEPanel extends JPanel
{
public Frame parentFrame;
private Timer timer;
public int logicLoops;
public double prevFPS;
boolean timerReady;

// The MidiPlayer object is used by the example to play the midi.

public MidiPlayer midiPlayer;

public SSCCEPanel(Frame parent)
{
super(true);
parentFrame = parent;
this.setFocusable(true);

Toolkit.getDefaultToolkit().sync();
logicLoops = 0;

midiPlayer = new MidiPlayer();

TimerListener timerListener = new TimerListener();
prevFPS = 0;
timerReady = true;
timer = new Timer(0,timerListener);
this.setFPS(60);
timer.start();
}

/**
* setFPS()
* Preconditions: fps is a quantity of frames per second
* Postconditions: Sets the timer's refresh rate so that it
* fires fps times per second.
**/

public void setFPS(int fps)
{
int mspf = (int) (1000.0 /fps + 0.5);
timer.setDelay(mspf);
}


/**
* This is the JPanel's timer listener. It runs the example's logic and repaint
* methods each time it gets a timer signal.
**/

private class TimerListener implements ActionListener
{
long startTime = System.currentTimeMillis();
long lastTime = this.startTime;
int ticks = 0;

public void actionPerformed(ActionEvent e)
{
Object source = e.getSource();
if(source == timer)
{
// perform a loop through the game's logic and repaint.

synchronized(this)
{
if(timerReady)
{
timerReady = false;
runSSCCELogic();
repaint();
timerReady = true;
}
}

// Logic for Frames per Second counter

this.ticks++;

long currentTime = System.currentTimeMillis();

if(currentTime - startTime >= 500)
{
prevFPS = 1000.0 * ticks/(1.0*currentTime - startTime);
System.out.println(prevFPS);
startTime = currentTime;
ticks = 0;
}

lastTime = currentTime;
}
}
}


/**
* repaints the SSCCE.
* This just shows the current FPS.
**/

public void paintComponent(Graphics g)
{
super.paintComponent(g);

Graphics2D g2D = (Graphics2D) g;
double roundedFPS = Math.round(prevFPS*10)/10.0;

g2D.setColor(new Color(0x000000));
g2D.drawString("FPS: " + roundedFPS, 20,20);
g.dispose();
}

/**
* runSSCCEELogic()
* This is where the run-time logic for the SSCCE example is.
* All it does is load and play a midi called "mymidi.mid" which is located in the same directory.
**/

public void runSSCCELogic()
{
if(logicLoops == 1)
{
midiPlayer.load("http://www.vgmusic.com/music/computer/microsoft/windows/touhou_6_stage3_boss.mid");
midiPlayer.play(true);
}

logicLoops++;
}
}



/**
* MidiPlayer
* A class that allows midi files to be loaded and played.
**/

class MidiPlayer
{
private Sequence seq;
private Sequencer seqr;
private Synthesizer synth;
private Receiver receiver;
private File midiFile;
private String midiID;
private boolean loaded;
private boolean usingHardwareSoundbank;

// CONSTRUCTORS

public MidiPlayer()
{
loaded = false;
try
{
seqr = MidiSystem.getSequencer();
synth = MidiSystem.getSynthesizer();
}
catch(Exception e)
{
System.out.println("MIDI error: It appears your system doesn't have a MIDI device or your device is not working.");
}
}

/**
* MidiPlayer(String fileName)
* Constructor that also loads an initial midi file.
* Preconditions: fileName is the name of the midi file to be loaded.
* Postconditions: The MidiPlayer is created and loaded with the midi specified by fileName.
**/

public MidiPlayer(String fileName)
{
this();
load(fileName);
}


// DATA METHODS

/**
* load(String fileName)
* loads a midi file into this MidiPlayer.
* Preconditions: fileName is the name of the midi file to be loaded.
* Postconditions: fileName is loaded and is ready to be played.
**/

public void load(String fileName)
{
this.unload();
try
{
URL midiURL = new URL(fileName);
// midiFile = new File(fileName);
seq = MidiSystem.getSequence(midiURL);

seqr.open();
synth.open();

System.out.println("MidiDeviceInfo: ");
for(MidiDevice.Info info : MidiSystem.getMidiDeviceInfo())
{
System.out.println("\t" + info);
}
System.out.println();

if(synth.getDefaultSoundbank() == null)
{
receiver = MidiSystem.getReceiver();
usingHardwareSoundbank = true;
System.out.println("using hardware soundbank");
}
else
{
receiver = synth.getReceiver();
usingHardwareSoundbank = false;
System.out.println("using default software soundbank:" + synth.getDefaultSoundbank());
}
seqr.getTransmitter().setReceiver(receiver);

seqr.setSequence(seq);
loaded = true;
}
catch(IOException ioe)
{
System.out.println("MIDI error: Problem occured while reading " + midiFile.getName() + ".");
}
catch(InvalidMidiDataException imde)
{
System.out.println("MIDI error: " + midiFile.getName() + " is not a valid MIDI file or is unreadable.");
}
catch(Exception e)
{
System.out.println("MIDI error: Unexplained error occured while loading midi.");
}
}

/**
* unload()
* Unloads the current midi from the MidiPlayer and releases its resources from memory.
**/

public void unload()
{
this.stop();
seqr.close();
midiFile = null;
loaded = false;
}

// OTHER METHODS

/**
* setMidiID(String id)
* associates a String ID with the current midi.
* Preconditions: id is the ID we are associating with the current midi.
**/

public void setMidiID(String id)
{
midiID = id;
}

/**
* getMidiID(String id)
*
**/

public String getMidiID()
{
return new String(midiID);
}

/**
* play(boolean reset)
* plays the currently loaded midi.
* Preconditions: reset tells our midi whether or nor to begin playing from the start of the midi file's current loop start point.
* Postconditions: If reset is true, then the loaded midi begins playing from its loop start point (default 0).
* If reset is false, then the loaded midi resumes playing from its current position.
**/

public void play(boolean reset)
{
if(reset)
seqr.setTickPosition(seqr.getLoopStartPoint());
seqr.start();
}

/**
* stop()
* Pauses the current midi if it was playing.
**/

public void stop()
{
if(seqr.isOpen())
seqr.stop();
}

/**
* isRunning()
* Returns true if the current midi is playing. Returns false otherwise.
**/

public boolean isRunning()
{
return seqr.isRunning();
}


/**
* loop(int times)
* Sets the current midi to loop from start to finish a specific number of times.
* Preconditions: times is the number of times we want our midi to loop.
* Postconditions: The current midi is set to loop times times.
* If times = -1, the current midi will be set to loop infinitely.
**/

public void loop(int times)
{
loop(times,0,-1);
}

/**
* loop(int times)
* Sets the current midi to loop from a specified start point to a specified end point a specific number of times.
* Preconditions: times is the number of times we want our midi to loop.
* start is our loop's start point in ticks.
* end is our loop's end point in ticks.
* Postconditions: The current midi is set to loop from tick start to tick end times times.
* If times = -1, the current midi will be set to loop infinitely.
**/

public void loop(int times, long start, long end)
{
if(start < 0)
start = 0;
if(end > seqr.getSequence().getTickLength() || end <= 0)
end = seqr.getSequence().getTickLength();

if(start >= end && end != -1)
start = end-1;

seqr.setLoopStartPoint(start);
seqr.setLoopEndPoint(end);

if(times == -1)
seqr.setLoopCount(Sequencer.LOOP_CONTINUOUSLY);
else
seqr.setLoopCount(times);

}


public void setVolume(double vol)
{
try
{
if(usingHardwareSoundbank)
{
ShortMessage volumeMessage = new ShortMessage();
for ( int i = 0; i < 16; i++ )
{
volumeMessage.setMessage( ShortMessage.CONTROL_CHANGE, i, 7, (int)(vol*127) );
receiver.send( volumeMessage, -1 );
}
}
else
{
MidiChannel[] channels = synth.getChannels();
for( int c = 0; channels != null && c < channels.length; c++ )
{
channels[c].controlChange( 7, (int)( vol*127) );
}
}
}
catch ( Exception e )
{
e.printStackTrace();
}
}

}

最佳答案

MIDI 的音质取决于生成声音的合成器。它不应该与您的代码有任何关系。

很可能是您的声卡出现问题,但这并不总是产生声音的原因,尤其是现在。在 Windows 下,微软有一个软件合成器可以完成这一切。无论如何,这与您的代码没有任何关系。

关于Java midi播放质量不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10441814/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com