Qual è il modo più semplice per generare un suono sinusoidale a qualsiasi frequenza in Java? Una dimensione di esempio superiore a 2 byte sarebbe di aiuto, ma non importa.Generatore sonoro sinusoidale in Java
Grazie
Qual è il modo più semplice per generare un suono sinusoidale a qualsiasi frequenza in Java? Una dimensione di esempio superiore a 2 byte sarebbe di aiuto, ma non importa.Generatore sonoro sinusoidale in Java
Grazie
Vedere Beeper
per un esempio autonomo.
Forse qualcosa di più semplice?
che il 51 linee di frammento (ripetuti qui sotto - distanziati per singola linea & commenti in-line), come visualizzato nella parte superiore della risposta legata, è quanto di più semplice come la generazione di un tono gets (OK, è possibile prendere 5+ linee per l'armonica).
Le persone sembrano presumere che dovrebbe essere un metodo incorporato nel toolkit per produrre un tono puro. Non lo è, e ci vuole un po 'di calcolo per crearne uno.
/** Generates a tone, and assigns it to the Clip. */
public void generateTone()
throws LineUnavailableException {
if (clip!=null) {
clip.stop();
clip.close();
} else {
clip = AudioSystem.getClip();
}
boolean addHarmonic = harmonic.isSelected();
int intSR = ((Integer)sampleRate.getSelectedItem()).intValue();
int intFPW = framesPerWavelength.getValue();
float sampleRate = (float)intSR;
// oddly, the sound does not loop well for less than
// around 5 or so, wavelengths
int wavelengths = 20;
byte[] buf = new byte[2*intFPW*wavelengths];
AudioFormat af = new AudioFormat(
sampleRate,
8, // sample size in bits
2, // channels
true, // signed
false // bigendian
);
int maxVol = 127;
for(int i=0; i<intFPW*wavelengths; i++){
double angle = ((float)(i*2)/((float)intFPW))*(Math.PI);
buf[i*2]=getByteValue(angle);
if(addHarmonic) {
buf[(i*2)+1]=getByteValue(2*angle);
} else {
buf[(i*2)+1] = buf[i*2];
}
}
try {
byte[] b = buf;
AudioInputStream ais = new AudioInputStream(
new ByteArrayInputStream(b),
af,
buf.length/2);
clip.open(ais);
} catch(Exception e) {
e.printStackTrace();
}
}
Utilizzare il Java Sound API e Math.sin
per creare i livelli d'onda attuali.
http://www.developer.com/java/other/article.php/2226701 ha un eccellente tutorial su questo che ho fatto riferimento qualche tempo fa. http://jsresources.org/examples/ era un altro riferimento utile.
Se volete qualche codice facile per iniziare, questo dovrebbe aiutare
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
public class SinSynth {
//
protected static final int SAMPLE_RATE = 16 * 1024;
public static byte[] createSinWaveBuffer(double freq, int ms) {
int samples = (int)((ms * SAMPLE_RATE)/1000);
byte[] output = new byte[samples];
//
double period = (double)SAMPLE_RATE/freq;
for (int i = 0; i < output.length; i++) {
double angle = 2.0 * Math.PI * i/period;
output[i] = (byte)(Math.sin(angle) * 127f); }
return output;
}
public static void main(String[] args) throws LineUnavailableException {
final AudioFormat af = new AudioFormat(SAMPLE_RATE, 8, 1, true, true);
SourceDataLine line = AudioSystem.getSourceDataLine(af);
line.open(af, SAMPLE_RATE);
line.start();
boolean forwardNotBack = true;
for(double freq = 400; freq <= 800;) {
byte [] toneBuffer = createSinWaveBuffer(freq, 50);
int count = line.write(toneBuffer, 0, toneBuffer.length);
if(forwardNotBack) {
freq += 20;
forwardNotBack = false; }
else {
freq -= 10;
forwardNotBack = true;
} }
line.drain();
line.close();
}
}
questo è facile da leggere, ma da dove viene il numero magico 127f? – nont
@nont sin restituisce un valore compreso tra -1,0 e 1,0, moltiplicandolo per 127 fornisce un'onda sinusoidale con una scala completa di un byte da -127 a +127, (viene convertito in un byte) –
vorrei solo far notare che c'è un algoritmo molto efficiente per la generazione di onde sinusoidali.
DSP Trucco: sinusoidale Generatore di toni http://www.dspguru.com/dsp/tricks/sine_tone_generator
In un primo consiglio che crea classe Nota, che restituiscono frequenze di nota, e convertirlo in array di byte.
Poi streaming molto facilmente
protected static final int SAMPLE_RATE = 8 * 1024;
public static void main(String[] args) throws LineUnavailableException {
final AudioFormat af = new AudioFormat(SAMPLE_RATE, 8, 1, true, true);
SourceDataLine line = AudioSystem.getSourceDataLine(af);
line.open(af, SAMPLE_RATE);
line.start();
// fist argument is duration of playing note
byte[] noteDo = Note.DO.getTone(1, SAMPLE_RATE);
byte[] noteRe = Note.RE.getTone(0.5, SAMPLE_RATE);
byte[] noteMi = Note.MI.getTone(1.5, SAMPLE_RATE);
line.write(noteDo, 0, noteDo.length);
line.write(noteRe, 0, noteRe.length);
line.write(noteMi, 0, noteMi.length);
line.drain();
line.close();
}
public enum Note {
DO(0.0f), DO_DIEZ(1.0f),
RE(2.0f), RE_DIEZ(3.0f),
MI(4.0f),
FA(5.0f), FA_DIEZ(6.0f),
SOL(7.0f),SOL_DIEZ(8.0f),
LYA(9.0f),LYA_DIEZ(10.0f),
SI(11.0f);
private final double mPhase;
Note(double phase) {
mPhase = phase;
}
public double getNoteFrequencies() {
double index = getmPhase()/ 12.0d;
return 440 * Math.pow(2, index);
}
public static Note getNote(double phase) throws Exception {
Note findNote = null;
for (Note note : Note.values()){
if (note.getmPhase() == phase){
findNote = note;
}
}
if (findNote == null)
throw new Exception("Note not found: Ilegal phase " + phase);
else
return findNote;
}
public byte[] getTone(double duration, int rate){
double frequencies = getNoteFrequencies();
int maxLength = (int)(duration * rate);
byte generatedTone[] = new byte[2 * maxLength];
double[] sample = new double[maxLength];
int idx = 0;
for (int x = 0; x < maxLength; x++){
sample[x] = sine(x, frequencies/rate);
}
for (final double dVal : sample) {
final short val = (short) ((dVal * 100f));
// in 16 bit wav PCM, first byte is the low order byte
generatedTone[idx++] = (byte) (val & 0x00ff);
generatedTone[idx++] = (byte) ((val & 0xff00) >>> 8);
}
return generatedTone;
}
private double sine(int x, double frequencies){
return Math.sin( 2*Math.PI * x * frequencies);
}
public double getmPhase() {
return mPhase;
}
}
Vedere anche ['Nota'] (http://stackoverflow.com/a/2065693/230513). – trashgod