public void SetFricationTaps(IntonationModel model) { double fricationAmplitude = WaveHelper.CalculateAmplitude(model.FricationVolume); /* CALCULATE POSITION REMAINDER AND COMPLEMENT */ var integerPart = (int)model.FricationPosition; var complement = model.FricationPosition - (double)integerPart; var remainder = 1.0 - complement; /* SET THE FRICATION TAPS */ for (int i = 0; i < 8; i++) { if (i == integerPart) { FricationTap[i] = remainder * fricationAmplitude; if ((i + 1) < 8) { FricationTap[++i] = complement * fricationAmplitude; } } else { FricationTap[i] = 0.0; } } }
public ModelToWaveService(ThroatModelParameters parameters) { if (parameters.TubeLength <= 0) { throw new Exception("Illegal tube length."); } _parameters = parameters; ///CALCULATE THE SAMPLE RATE, BASED ON NOMINAL ///TUBE LENGTH AND SPEED OF SOUND var speedOfSound = WaveHelper.SpeedOfSound(parameters.TubeTemp); _controlPeriod = Math.Round((speedOfSound * parameters.TotalSections * parameters.SectionLength) / (parameters.TubeLength * parameters.InControlRate)); SampleRate = parameters.InControlRate * _controlPeriod; //var actualTubeLength = (speedOfSound * totalSections * sectionLength) / sampleRate; _nyquist = SampleRate / 2.0; _breathinessFactor = parameters.GlotSrcBreathiness / 100d; _crossmixFactor = 1.0d / WaveHelper.CalculateAmplitude(parameters.NoiseCrossmixOffset); _dampingFactor = (1.0d - (parameters.JunctionLoss / 100d)); _waveTable = new WaveTable(SampleRate, parameters); _bandpassFilter = new BandpassFilter(); _vocalTract = new VocalTract(parameters, _nyquist, SampleRate); // initializeFIRFilter(FIR_BETA, FIR_GAMMA, FIR_CUTOFF); // /* INITIALIZE THE SAMPLE RATE CONVERSION ROUTINES */ // initializeConversion(); /* INITIALIZE THE TEMPORARY OUTPUT FILE */ // tempFilePtr = tmpfile(); // rewind(tempFilePtr); }
private void InitializeThroat(ThroatModelParameters parameters, double sampleRate) { ta0 = (parameters.ThroatFreqCutoff * 2.0) / sampleRate; tb1 = 1.0 - ta0; throatGain = WaveHelper.CalculateAmplitude(parameters.ThroatVolume); }
public static string WriteWaveFile(IEnumerable <double> waveform, double sampleRate, ThroatModelParameters parameters) { var outputScale = 0.25; var rangeMax = 32767d; var balance = 0; // var sampleRateRatio = outputRate / sampleRate; var(fileStream, path) = CreateFileStream(); //WriteWaveFileHeader(2, waveform.Count(), parameters.OutputSampleRate, fileStream); WriteWaveFileHeader(2, waveform.Count(), sampleRate, fileStream); var scale = outputScale * (rangeMax / waveform.Max()) * WaveHelper.CalculateAmplitude(parameters.MasterVolume); var leftScale = -((balance / 2.0) - 0.5) * scale * 2.0; var rightScale = ((balance / 2.0) + 0.5) * scale * 2.0; foreach (var data in waveform) { WriteShort(fileStream, (short)Math.Round(data * leftScale)); WriteShort(fileStream, (short)Math.Round(data * rightScale)); } fileStream.Flush(); fileStream.Close(); return(path); // int endPtr; // /* CALCULATE END POINTER */ // endPtr = fillPtr - padSize; // /* ADJUST THE END POINTER, IF LESS THAN ZERO */ // if (endPtr < 0) // endPtr += BUFFER_SIZE; // /* ADJUST THE ENDPOINT, IF LESS THEN THE EMPTY POINTER */ // if (endPtr < emptyPtr) // endPtr += BUFFER_SIZE; /* UPSAMPLE LOOP (SLIGHTLY MORE EFFICIENT THAN DOWNSAMPLING) */ // if (sampleRateRatio >= 1.0) { // while (emptyPtr < endPtr) { // int index; // unsigned int filterIndex; // double output, interpolation, absoluteSampleValue; // /* RESET ACCUMULATOR TO ZERO */ // output = 0.0; // /* CALCULATE INTERPOLATION VALUE (STATIC WHEN UPSAMPLING) */ // interpolation = (double)mValue(timeRegister) / (double)M_RANGE; // /* COMPUTE THE LEFT SIDE OF THE FILTER CONVOLUTION */ // index = emptyPtr; // for (filterIndex = lValue(timeRegister); filterIndex < FILTER_LENGTH; srDecrement(&index,BUFFER_SIZE), filterIndex += filterIncrement) { // output += (buffer[index] * (h[filterIndex] + (deltaH[filterIndex] * interpolation))); // } // /* ADJUST VALUES FOR RIGHT SIDE CALCULATION */ // timeRegister = ~timeRegister; // interpolation = (double)mValue(timeRegister) / (double)M_RANGE; // /* COMPUTE THE RIGHT SIDE OF THE FILTER CONVOLUTION */ // index = emptyPtr; // srIncrement(&index,BUFFER_SIZE); // for (filterIndex = lValue(timeRegister); filterIndex < FILTER_LENGTH; srIncrement(&index,BUFFER_SIZE), filterIndex += filterIncrement) { // output += (buffer[index] * (h[filterIndex] + (deltaH[filterIndex] * interpolation))); // } // /* RECORD MAXIMUM SAMPLE VALUE */ // absoluteSampleValue = fabs(output); // if (absoluteSampleValue > maximumSampleValue) // maximumSampleValue = absoluteSampleValue; // /* INCREMENT SAMPLE NUMBER */ // numberSamples++; // /* OUTPUT THE SAMPLE TO THE TEMPORARY FILE */ // fwrite((char *)&output, sizeof(output), 1, tempFilePtr); // /* CHANGE TIME REGISTER BACK TO ORIGINAL FORM */ // timeRegister = ~timeRegister; // /* INCREMENT THE TIME REGISTER */ // timeRegister += timeRegisterIncrement; // /* INCREMENT THE EMPTY POINTER, ADJUSTING IT AND END POINTER */ // emptyPtr += nValue(timeRegister); // if (emptyPtr >= BUFFER_SIZE) { // emptyPtr -= BUFFER_SIZE; // endPtr -= BUFFER_SIZE; // } // /* CLEAR N PART OF TIME REGISTER */ // timeRegister &= (~N_MASK); // } // } // else { /* DOWNSAMPLING CONVERSION LOOP */ // while (emptyPtr < endPtr) { // int index; // unsigned int phaseIndex, impulseIndex; // double absoluteSampleValue, output, impulse; // /* RESET ACCUMULATOR TO ZERO */ // output = 0.0; // /* COMPUTE P PRIME */ // phaseIndex = (unsigned int)rint(((double)fractionValue(timeRegister)) * sampleRateRatio); // /* COMPUTE THE LEFT SIDE OF THE FILTER CONVOLUTION */ // index = emptyPtr; // while ((impulseIndex = (phaseIndex>>M_BITS)) < FILTER_LENGTH) { // impulse = h[impulseIndex] + (deltaH[impulseIndex] * (((double)mValue(phaseIndex)) / (double)M_RANGE)); // output += (buffer[index] * impulse); // srDecrement(&index,BUFFER_SIZE); // phaseIndex += phaseIncrement; // } // /* COMPUTE P PRIME, ADJUSTED FOR RIGHT SIDE */ // phaseIndex = (unsigned int)rint(((double)fractionValue(~timeRegister)) * sampleRateRatio); // /* COMPUTE THE RIGHT SIDE OF THE FILTER CONVOLUTION */ // index = emptyPtr; // srIncrement(&index,BUFFER_SIZE); // while ((impulseIndex = (phaseIndex>>M_BITS)) < FILTER_LENGTH) { // impulse = h[impulseIndex] + (deltaH[impulseIndex] * (((double)mValue(phaseIndex)) / (double)M_RANGE)); // output += (buffer[index] * impulse); // srIncrement(&index,BUFFER_SIZE); // phaseIndex += phaseIncrement; // } // /* RECORD MAXIMUM SAMPLE VALUE */ // absoluteSampleValue = fabs(output); // if (absoluteSampleValue > maximumSampleValue) // maximumSampleValue = absoluteSampleValue; // /* INCREMENT SAMPLE NUMBER */ // numberSamples++; // /* OUTPUT THE SAMPLE TO THE TEMPORARY FILE */ // fwrite((char *)&output, sizeof(output), 1, tempFilePtr); // /* INCREMENT THE TIME REGISTER */ // timeRegister += timeRegisterIncrement; // /* INCREMENT THE EMPTY POINTER, ADJUSTING IT AND END POINTER */ // emptyPtr += nValue(timeRegister); // if (emptyPtr >= BUFFER_SIZE) { // emptyPtr -= BUFFER_SIZE; // endPtr -= BUFFER_SIZE; // } // /* CLEAR N PART OF TIME REGISTER */ // timeRegister &= (~N_MASK); // } // } }
public IEnumerable <double> Synthesize(IEnumerable <IntonationModel> model) { double frequency, amplitude, aspVol, pulse, noise, pulsedNoise, signal, crossmix; /* CONTROL RATE LOOP */ foreach (var modelSection in model) { /* SAMPLE RATE LOOP */ for (int i = 0; i < _controlPeriod; i++) { /* CONVERT PARAMETERS HERE */ frequency = WaveHelper.CaclulateFrequency(modelSection.Pitch); amplitude = WaveHelper.CalculateAmplitude(modelSection.GlotVolume); aspVol = WaveHelper.CalculateAmplitude(modelSection.AspirationVolume); _vocalTract.CalculateTubeCoefficients(modelSection, _parameters); _vocalTract.SetFricationTaps(modelSection); _bandpassFilter.Update(modelSection.FricationBW, modelSection.FricationCF, SampleRate); noise = WaveHelper.Noise(); /* UPDATE THE SHAPE OF THE GLOTTAL PULSE, IF NECESSARY */ if (_parameters.GlotSrcType == GlotSrcType.Pulse) { _waveTable.UpdateWavetable(amplitude); } /* CREATE GLOTTAL PULSE (OR SINE TONE) */ pulse = _waveTable.Oscillator(frequency); /* CREATE PULSED NOISE */ pulsedNoise = noise * pulse; /* CREATE NOISY GLOTTAL PULSE */ pulse = amplitude * ((pulse * (1.0 - _breathinessFactor)) + (pulsedNoise * _breathinessFactor)); /* CROSS-MIX PURE NOISE WITH PULSED NOISE */ if (_parameters.PulseModulationOfNoise) { crossmix = amplitude * _crossmixFactor; crossmix = (crossmix < 1.0) ? crossmix : 1.0; signal = (pulsedNoise * crossmix) + (noise * (1.0 - crossmix)); } else { signal = noise; } /* PUT SIGNAL THROUGH VOCAL TRACT */ signal = _vocalTract.CalculateVocalTractSignal(((pulse + (aspVol * signal)) * _parameters.VocalTractScale), _bandpassFilter.Filter(signal), _dampingFactor); /* PUT PULSE THROUGH THROAT */ signal += _vocalTract.CalculateThroatSignal(pulse * _parameters.VocalTractScale); // /* OUTPUT SAMPLE HERE */ // dataFill(signal); yield return(signal); // /* DO SAMPLE RATE INTERPOLATION OF CONTROL PARAMETERS */ // sampleRateInterpolation(); } } yield break; }