问题
I want to find, how notes were built. Example for a Instrument (Violin or Piano), The Note LA4 (A4) has main (or central) frequency FC at 440Hz with a Specific Amplitude AC, but also it must has other frequencies (harmonics?) FH with other amplitudes AH.
The Harmonics have other frequencies that are dependant of Main Frequency with amplitudes (almost) less than the amplitude of Main Frequency.
Forming (building) Notes
I want to know how is formed (established) the notes (No time is considered).
Example: A4 = AC(FC) + AH1(FH1)+ AH2(FH2) + AH3(FH3) + AH4(FH4)....AHn(FHn) Maybe, FH1 = 2*FC, FH2 = 3*FC, FH3 = 4*FC, and so on....
Comparing between instruments (Violin and Piano)
For Piano, The Note LA4 (A4) has main frequency FC at 440Hz, and Maybe, FC(Piano) = FC(Violin), FH1(Piano) = FH1(Violin), FH2(Piano) = FH2(Violin), and so on....
But, AC(Piano) != AC(Violin), AH1(Piano) != AH1(Violin), AH2(Piano) != AH2(Violin), and so on....
Example of my question is: http://www.phys.unsw.edu.au/jw/sound.spectrum.html
I want to play this notes avoiding MIDI format, this can be implemented in Java/C# (or other language programming) Later, and more control of my sounds.
Thank you.
Ana
回答1:
I have this...
int iTone = 40; //Tone to be interpreted
iSmplRate = 32000; //Sample Rate
int NumBytesPerSample = 16; // 8 or 16
int NumChannels = 2; //1 Mono, 2 Stereo
double Duration = 6.5; //Seconds performing
Short sAmplit = 1200;
int iNumSmpl = (int)(SampleRate*Duration);
NumTotalBytes = (int)(SampleRate*Duration*NumBytesPerSample*NumChannels);
ByteBuffer bbWav = ByteBuffer.allocate(NumTotalBytes);
double dMaxInstr = (double)Short.MIN_VALUE;
double dMinInstr = (double)Short.MAX_VALUE;
//Amplitude for violin's armonics
double[] violAmps = {1.0, 0.286699025, 0.150079537, 0.042909002,
0.203797365, 0.229228698, 0.156931925,
0.115470898, 0.0, 0.097401803, 0.087653465,
0.052331036, 0.052922462, 0.038850593,
0.053554676, 0.053697434, 0.022270261,
0.013072562, 0.008585879, 0.005771505,
0.004343925, 0.002141371, 0.005343231,
0.000530244, 0.004711017, 0.009014153};
//Amplitude for piano's armonics
double[] pianAmps = {1.0, 0.399064778, 0.229404484, 0.151836061,
0.196754229, 0.093742264, 0.060871957,
0.138605419, 0.010535002, 0.071021868,
0.029954614, 0.051299684, 0.055948288,
0.066208224, 0.010067391, 0.00753679,
0.008196947, 0.012955577, 0.007316738,
0.006216476, 0.005116215, 0.006243983,
0.002860679, 0.002558108, 0.0, 0.001650392};
double[] operator = {1.0};
if (instrument.equals("violin")) {
operator = violAmps;
}
if (instrument.equals("piano")) {
operator = pianAmps;
}
double dFreq = 440.0*Math.pow(2.0, (iTone-69)/12.0;
double dFreqRel = iSmplRate/dFreq;
Integer iSampleInstrument = null;
double PI2 = 2*Math.PI;
int[] iSamplesInstr = new int[iNumSmpl];
for (int i = 0;i < iNumSmpl; i++) {
Double Angle = i*PI2/dFreqRel;
Double dInstrument = 0.0;
for (int a = 1; a <=operator.length; a++) {
dInstrument += operator[a-1]*Math.sin((double)a*Angle);
}
dMaxInstr = (dInstrument>dMaxInstr)?dInstrument:dMaxInstr;
dMinInstr = (dInstrument<dMinInstr)?dInstrument:dMinInstr;
iSampleInstrument = (int)(sAmplit*dInstrument);
if (instrument.equals("violin")) {
double FreqEnvV = iSmplRate/6.0;
double FracEnvV = 35.0;
double dEnvViolin = sAmplit*DStepperExt(Math.sin(1.0*i*PI2/FreqEnvV),4)/FracEnvV;
iSampleInstrument = (int)(iSampleInstrument+dEnvViolin);
}
if (instrument.equals("piano")) {
double FracEnvP = 8.0/10.0;
double AngP = (double)i/(iSmplRate*FracEnvP);
double EnvPiano = 1.0/Math.exp(AngP);
iSampleInstrument = (int)(iSampleInstrument*EnvPiano);
}
dMxSmplInstr = (iSampleInstrument>dMxSmplInstr)?iSampleInstrument:dMxSmplInstr;
dMnSmplInstr = (iSampleInstrument<dMnSmplInstr)?iSampleInstrument:dMnSmplInstr;
iSamplesInstr[i] = iSampleInstrument;
}
double dMaxAbs =
(Math.abs(dMaxInstr)>Math.abs(dMinInstr))?Math.abs(dMaxInstr):Math.abs(dMinInstr);
double dMxAbsSmpl =
(Math.abs(dMxSmplInstr)>Math.abs(dMnSmplInstr))?Math.abs(dMxSmplInstr):Math.abs(dMnSmplInstr);
double dNormal = 1.0;
if (dMxAbsSmpl > 32768.0) {
dNormal = 32768.0/dMxAbsSmpl;
}
for (int i = 0;i < iNumSmpl; i++) {
short sSampleInst = (short)(iSamplesInstr[i]*dNormal);
try {
if (iNumByteSmpl == 2) {
bbWav.put((byte)((sSampleInst >> 0) & 0xFF));
bbWav.put((byte)((sSampleInst >> 8) & 0xFF));
if (iNumChnnls == 2) {
bbWav.put((byte)((sSampleInst >> 0) & 0xFF));
bbWav.put((byte)((sSampleInst >> 8) & 0xFF));
}
} else {
byte ByteSample = (byte)((sSampleInst >> 8) & 0xFF);
short ShrtSample = (short)(ByteSample & 0xFF);
ShrtSample += 128;
bbWav.put((byte)(ShrtSample & 0xFF));
if (iNumChnnls == 2) {
bbWav.put((byte)(ShrtSample & 0xFF));
}
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
This code is used in Violin instrument:
private Double DStepperExt(Double Val, Integer Steps) {
//Return a value inside in range defined by step
//Divide [-1.0,1.0]/(Steps-1), retorning the value according to the range
//The value must be between 0.0 and 1.0
if (Steps <= 0.0) {
return 0.0;
}
if (Val != -1.0 && Val != 1.0) {
Val = Val - Val.intValue();
}
Double sDouble = new Double(Steps-1);
Double bdStep = 2.0/sDouble;
Double bdRef = bdStep/2.0;
bdRef = bdRef - 1.0;
Double bdInit = -1.0;
Double bdRet = null;
for (int c = 0; c<=sDouble;c++) {
if (Val < bdRef) {
bdRet = bdInit;
break;
} else {
bdInit = bdInit+bdStep;
bdRef = bdRef+bdStep;
}
}
return Math.min(bdRet.doubleValue(),1.0);
}
Try this code, my sound isn't perfect but is very similar.
回答2:
Be aware that what you are undertaking is a huge task. If your goal is to create your own synthesizer that can sound like a piano, violin, etc by adding together harmonics with specific amplitudes then it is incredibly difficult to create a sound that is in any way realistic. The harmonics of an acoustic instrument vary over time in a complex fashion. As guidot notes, the attack and delay parts of sound will be very different. If you try to measure the relative amplitudes of a real instrument at a number of points over time and then synthesise the sinusoids then the best you will achieve is something that will sound like a child's toy.
If that's what you want to do then you will need to analyse the spectrum over time of the sounds you want to emulate. The easiest way I would suggest is using something like Matlab, Octave or Scipy. If you want visualisations then try Sonic Visualiser or Marsyas.
If however you want to create realistic playback then you have two options. One is to use Wavetable synthesis, which is how many cheap synthesisers (especially ones on PC soundcards) work. The other is to look into Physical Modelling Synthesis which simulates the physics of an instrument to create realistic sounds.
回答3:
If I understand correctly, you are trying to do a fourier synthesis, hoping that something similar to the original instrument will result. I see the chances for success quite slim:
- it won't work using midi, since this would require pure sine waves to combine (which are not available by standard MIDI GS instruments)
- one needs huge amount of data difficult to come by; note,
that your coefficients are not specific to "piano" alone but also vary with
the pitch, so "piano a5" has different values from "piano a6"
- this model assumes the stable state of the tone (a different goal is not achievable by adding sine waves); the characteristic of an instrument is however more determined by its attack phase
I would recommend John Pierce, The Science of Musical Sound for an introduction.
来源:https://stackoverflow.com/questions/10702942/note-synthesis-harmonics-violin-piano-guitar-bass-frequencies-midi