예제 #1
0
        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);
        }
예제 #3
0
        private void InitializeThroat(ThroatModelParameters parameters, double sampleRate)
        {
            ta0 = (parameters.ThroatFreqCutoff * 2.0) / sampleRate;
            tb1 = 1.0 - ta0;

            throatGain = WaveHelper.CalculateAmplitude(parameters.ThroatVolume);
        }
예제 #4
0
        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;
        }