Javy wbudowane funkcje Midi
off-the-shelf Java 8 JRE zdecydowanie ma to, czego konkretnie wymagane: wbudowana biblioteka syntezatorów. Jest to opisane szczegółowo w Synthesizing Sound.
A quite refined example zapewnia wizualny dostęp do klawiatury do próbkowanego syntezatora muzycznego.
Biblioteka javax.sound.midi zawiera instrumenty i umiejętność odtwarzania nut na podstawie MIDI i technologii instrumentów próbkowanych. Dźwięki nie są tak autentyczne jak w klasycznej linii instrumentów muzycznych Kurzweil, ale struktura wspiera ten poziom zaawansowania, jeśli chcesz wykonać własne próbkowanie w wielu zakresach wysokości dla jednego instrumentu i opracować szczegóły dość płynnego przejścia między zakresami.
Trivial Przykład szybki przegląd Wykorzystanie
Oto trywialny przykład klasa.
import javax.sound.midi.MidiSystem;
import javax.sound.midi.Synthesizer;
import javax.sound.midi.MidiChannel;
public class PlayMidiNote
{
private static void sleep(int iUSecs)
{
try
{
Thread.sleep(iUSecs);
}
catch (InterruptedException e)
{
}
}
public static void main(String[] args) throws Exception
{
if (args.length < 3 && args.length > 4)
{
System.out.println("usage: java PlayNote
<8.bit.midi.note.number> <8.bit.velocity>
<usec.duration> [<midi.channel>]");
System.exit(1);
}
int iMidiKey = Math.min(127, Math.max(0,
Integer.parseInt(args[0])));
int iVelocity = Math.min(127, Math.max(0,
Integer.parseInt(args[1])));
int iUSecsDuration = Math.max(0,
Integer.parseInt(args[2]));
int iChannel = args.length > 3
? Math.min(15, Math.max(0,
Integer.parseInt(args[3])))
: 0;
Synthesizer synth = MidiSystem.getSynthesizer();
synth.open();
MidiChannel[] channels = synth.getChannels();
MidiChannel channel = channels[iChannel];
channel.noteOn(iMidiKey, iVelocity);
sleep(iUSecsDuration);
channel.noteOff(iMidiKey);
synth.close();
}
}
Korzystanie wielowątkowości lub e implementacje javax.sound.midi.Sequencer jak te dostępne na github.com zapewni strukturę niezbędną do faktycznie tworzyć muzykę.
Waveform Generation
Jeśli chcesz wygenerować własne przebiegi zamiast przy użyciu próbek, to odpowiedź na twoje pytanie brzmi: „Nie”, więc można grać z tego tonu syntezatora pisałem na to pytanie . Ma kilka funkcji.
- Sterowanie nachyleniem (w cykli na sekundę)
- kontroli amplitudy (w krokach cyfrowych)
- min i max statystycznych wskazania, kiedy amplituda jest zbyt wysokie (co powoduje zakłócenia w sygnale z strzyżenie audio)
- Kontrola czasu trwania tonu (w sekundach)
- Kontrola względnej amplitudy dowolnej liczby harmonicznych (który określa jakość dźwięku lub fali, która jest jednym z kilku czynników, które tworzą nuty za barwę)
Syntezator ten nie posiada wielu funkcji syntezatorów generujących wysokie częstotliwości.
- rzeczywistym czas modyfikacji amplitudy zasadniczymi harmonicznych harmonicznych i innych w czasie trwania notatki
- nie odtwarza sekwencje nut (ale może być zmodyfikowany tak, aby to zrobić stosunkowo łatwo)
- nr obiekt na przesunięcie fazowe harmonicznych albo (ale to dość istotne niedociągnięcie, gdyż charakterystyki fazowe harmonicznych nie jest czymś ludzkie ucho jest w stanie wykryć)
SimpleSynth to dobra demonstracja
- Zasady syntezy dźwięku
- timbral efekt harmonicznych
- Zastosowanie Java generowania dźwięku tablice próbek
- Wprowadzanie próbek do tablicy bajtów
- Dostarczanie takich bajt array do systemu operacyjnego za pomocą linii
Standardową cyfrową terminologię audio użyto zarówno do nazewnictwa stałego, jak i zmiennych. Matematyka jest wyjaśniona w komentarzach.
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.SourceDataLine;
class SimpleSynth
{
private static int SAMPLE_BITS = 16;
private static int CHANNELS = 1;
private static boolean SIGNED_TRUE = true;
private static boolean BIG_ENDIAN_FALSE = false;
private static float CDROM_SAMPLE_FREQ = 44100;
private SourceDataLine line;
private double dDuration;
private double dCyclesPerSec;
private double dAmplitude;
private double[] adHarmonics;
private double dMin;
private double dMax;
public SimpleSynth(String[] asArguments) throws Exception
{
dDuration = Double.parseDouble(asArguments[0]);
dCyclesPerSec = Double.parseDouble(asArguments[1]);
dAmplitude = Double.parseDouble(asArguments[2]);
adHarmonics = new double[asArguments.length - 3];
for (int i = 0; i < adHarmonics.length; ++ i)
adHarmonics[i] = Double.parseDouble(
asArguments[i + 3]);
AudioFormat format = new AudioFormat(
CDROM_SAMPLE_FREQ, SAMPLE_BITS,
CHANNELS, SIGNED_TRUE, BIG_ENDIAN_FALSE);
line = AudioSystem.getSourceDataLine(format);
line.open();
line.start();
}
public void closeLine()
{
line.drain();
line.stop();
}
public void playSound()
{
// allocate and prepare byte buffer and its index
int iBytes = (int) (2.0 * (0.5 + dDuration)
* CDROM_SAMPLE_FREQ);
byte[] ab = new byte[iBytes];
int i = 0;
// iterate through sample radian values
// for the specified duration
short i16;
double dSample;
double dRadiansPerSample = 2.0 * Math.PI
* dCyclesPerSec/CDROM_SAMPLE_FREQ;
double dDurationInRadians = 2.0 * Math.PI
* dCyclesPerSec * dDuration;
dMin = 0.0;
dMax = 0.0;
for (double d = 0.0;
d < dDurationInRadians;
d += dRadiansPerSample)
{
// add principle and the dot product of harmonics
// and their amplitudes relative to the principle
dSample = Math.sin(d);
for (int h = 0; h < adHarmonics.length; ++ h)
dSample += adHarmonics[h]
* Math.sin((h + 2) * d);
// factor in amplitude
dSample *= dAmplitude;
// adjust statistics
if (dMin > dSample)
dMin = dSample;
if (dMax < dSample)
dMax = dSample;
// store in byte buffer
i16 = (short) (dSample);
ab[i ++] = (byte) (i16);
ab[i ++] = (byte) (i16 >> 8);
}
// send the byte array to the audio line
line.write(ab, 0, i);
}
public void printStats()
{
System.out.println("sample range was ["
+ dMin + ", " + dMax + "]"
+ " in range of [-32768, 32767]");
if (dMin < -32768.0 || dMax > 32767.0)
System.out.println("sound is clipping"
+ "(exceeding its range),"
+ " so use a lower amplitude");
}
public static void main(String[] asArguments)
throws Exception
{
if (asArguments.length < 3)
{
System.err.println("usage: java SimpleSynth"
+ " <duration>"
+ " <tone.cycles.per.sec>"
+ " <amplitude>"
+ " [<relative.amplitude.harmonic.2>"
+ " [...]]");
System.err.println("pure tone:"
+ " java SimpleSynth 1 440 32767");
System.err.println("oboe-like:"
+ " java SimpleSynth 1 440 15000 0 1 0 .9");
System.err.println("complex:"
+ " java SimpleSynth 1 440 800 .3"
+ " .5 .4 .2 .9 .7 5 .1 .9 12 0 3"
+ " .1 5.2 2.5 .5 1 7 6");
System.exit(0);
}
SimpleSynth synth = new SimpleSynth(asArguments);
synth.playSound();
synth.closeLine();
synth.printStats();
System.exit(0);
}
}
tematy badań, które Rozszerz podsumowujące Muzyka Fachowość
Istnieje kilka tematów przeczytać na, jeśli chcesz, aby stać się ekspertem cyfrowy syntezator.
- Cyfrowe wyjście audio
- Signal próbkowania
- kryteria Nyquist
- Jak zrywać harmonicznych na strunach instrumentu (takich jak gitara)
- Podstawowe trygonometrii, specjalnie funkcji sinus
Link do forum Sun nie działa. – RealHowTo
IIRC, dyskusja obejmowała [podejście] (http://stackoverflow.com/a/7782749/230513) ze względu na [Andrew Thompson] (http://stackoverflow.com/users/418556/andrew-thompson), cytowane [tutaj] (http://stackoverflow.com/a/2065693/230513). – trashgod