Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 3 of 3

Thread: frequencyModulation & phaseModulation at the sametime ?

  1. #1
    Junior Member
    Join Date
    Apr 2020
    Posts
    5

    frequencyModulation & phaseModulation at the sametime ?

    Anyone can help me to find the way to make AudioSynthWaveformsModulated to working with 3 input
    1. PitchEnvelope to control frequencyModulation.
    2. Modulation Oscillator to control phaseModulation.
    3. Lfo to control shape.

    Code:
    void AudioSynthWaveformModulated::update(void)
    {
    	audio_block_t *block, *moddata, *mod2data *shapedata;
    	int16_t *bp, *bp2, *end;
    	int32_t val1, val2;
    	int16_t magnitude15;
    	uint32_t i, ph, index, index2, scale, priorphase;
    	const uint32_t inc = phase_increment;
    
    	moddata = receiveReadOnly(0);
    	shapedata = receiveReadOnly(1);
    	mod2data = receiveReadOnly(2);
    
    	// Pre-compute the phase angle for every output sample of this update
    	ph = phase_accumulator;
    	priorphase = phasedata[AUDIO_BLOCK_SAMPLES-1];
    	if (moddata && modulation_type == 0) {
    		// Frequency Modulation
    		bp = moddata->data;
    		bp2 = mod2data->data;
    		for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
    			int32_t n = (*bp++) * modulation_factor; // n is # of octaves to mod
    		        uint32_t n2 = ((uint32_t)(*bp2++)) * phase_factor;
    			int32_t n2 = 
    			int32_t ipart = n >> 27; // 4 integer bits
    			n &= 0x7FFFFFF;          // 27 fractional bits
    			#ifdef IMPROVE_EXPONENTIAL_ACCURACY
    			// exp2 polynomial suggested by Stefan Stenzel on "music-dsp"
    			// mail list, Wed, 3 Sep 2014 10:08:55 +0200
    			int32_t x = n << 3;
    			n = multiply_accumulate_32x32_rshift32_rounded(536870912, x, 1494202713);
    			int32_t sq = multiply_32x32_rshift32_rounded(x, x);
    			n = multiply_accumulate_32x32_rshift32_rounded(n, sq, 1934101615);
    			n = n + (multiply_32x32_rshift32_rounded(sq,
    				multiply_32x32_rshift32_rounded(x, 1358044250)) << 1);
    			n = n << 1;
    			#else
    			// exp2 algorithm by Laurent de Soras
    			// https://www.musicdsp.org/en/latest/Other/106-fast-exp2-approximation.html
    			n = (n + 134217728) << 3;
    
    			n = multiply_32x32_rshift32_rounded(n, n);
    			n = multiply_32x32_rshift32_rounded(n, 715827883) << 3;
    			n = n + 715827882;
    			#endif
    			uint32_t scale = n >> (14 - ipart);
    			uint64_t phstep = (uint64_t)inc * scale;
    			uint32_t phstep_msw = phstep >> 32;
    			if (phstep_msw < 0x7FFE) {
    				ph += phstep >> 16;
    			} else {
    				ph += 0x7FFE0000;
    			}
    			phasedata[i] = ph + n2;
    			ph += inc;
    		}
    		release(moddata);
    		release(mod2data);

  2. #2
    Junior Member
    Join Date
    Apr 2020
    Posts
    5
    I found this code example in musicdsp.org
    It is the right way to do ?

    Code:
    /* Example implementation of digital oscillator with FM, PM, & AM */
    
    #define PI 3.14159265358979
    #define RADIANS_TO_INDEX (512.0 / (2.0 * PI))
    
    typedef struct{     /* oscillator data */
        double freq;   /* oscillator frequency in radians per sample */
        double phase;  /* accumulated oscillator phase in radians */
        double wavetable[512]; /* waveform lookup table */
    } OscilRec;
    
    
    /* oscil - compute 1 sample of oscillator output whose freq. phase and
    *    wavetable are in the OscilRec structure pointed to by orec.
    */
    double oscil(orec, fm, pm, am)
        OscilRec *orec;  /* pointer to the oscil's data */
        double fm; /* frequency modulation input  in radians per sample */
        double pm; /* phase modulation input      in radians */
        double am; /* amplitude modulation input  in any units you want */
    {
        long tableindex;            /* index into wavetable */
        double instantaneous_freq;  /* oscillator freq  + freq  modulation */
        double instantaneous_phase; /* oscillator phase + phase modulation */
        double output;              /* oscillator output */
    
        instantaneous_freq  = orec->freq  + fm; /* get instantaneous freq */
        orec->phase += instantaneous_freq;      /* accumulate phase */
        instantaneous_phase = orec->phase + pm; /* get instantaneous phase */
    
        /* convert to lookup table index */
        tableindex = RADIANS_TO_INDEX * instantaneous_phase;
        tableindex &= 511; /* make it mod 512 === eliminate multiples of 2*k*PI */
    
        output = orec->wavetable[tableindex] * am; /* lookup and mult by am input */
    
        return (output);  /* return oscillator output */
    }

  3. #3
    Junior Member
    Join Date
    Apr 2020
    Posts
    5
    This is the result and it work. yeah!! but I'm not sure it have any drawback.

    In synth_waveform.h, I add extra fuction call freqAndphaseModulation
    Code:
    void freqAndphaseModulation(float octaves, float degrees)
    	{
    		if (octaves > 12.0f) {
    			octaves = 12.0f;
    		} else if (octaves < 0.1f) {
    			octaves = 0.1f;
    		}
    		modulation_factor = octaves * 4096.0f;
    
    		if (degrees > 9000.0f) {
    			degrees = 9000.0f;
    		} else if (degrees < 30.0f) {
    			degrees = 30.0f;
    		}
    		phase_factor = degrees * (float)(65536.0 / 180.0);	
    		modulation_type = 2;
    	}
    Then, I implement freqAndphaseModulation_type in AudioSynthWaveformModulated::update
    Code:
    void AudioSynthWaveformModulated::update(void)
    {
    	audio_block_t *block, *freqModData, *phaseModData, *shapeData;
    	int16_t *bp, *bp2, *end;
    	int32_t val1, val2;
    	int16_t magnitude15;
    	uint32_t i, ph, index, index2, scale, priorphase;
    	const uint32_t inc = phase_increment;
    
    	freqModData = receiveReadOnly(0);
    	phaseModData = receiveReadOnly(1);
    	shapeData = receiveReadOnly(2);
    
    	// Pre-compute the phase angle for every output sample of this update
    	ph = phase_accumulator;
    	priorphase = phasedata[AUDIO_BLOCK_SAMPLES-1];
    	if (freqModData && modulation_type == 0) {
    		// Frequency Modulation
    		bp = freqModData->data;
    		for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
    			int32_t n = (*bp++) * modulation_factor; // n is # of octaves to mod
    			int32_t ipart = n >> 27; // 4 integer bits
    			n &= 0x7FFFFFF;          // 27 fractional bits
    			#ifdef IMPROVE_EXPONENTIAL_ACCURACY
    			// exp2 polynomial suggested by Stefan Stenzel on "music-dsp"
    			// mail list, Wed, 3 Sep 2014 10:08:55 +0200
    			int32_t x = n << 3;
    			n = multiply_accumulate_32x32_rshift32_rounded(536870912, x, 1494202713);
    			int32_t sq = multiply_32x32_rshift32_rounded(x, x);
    			n = multiply_accumulate_32x32_rshift32_rounded(n, sq, 1934101615);
    			n = n + (multiply_32x32_rshift32_rounded(sq,
    				multiply_32x32_rshift32_rounded(x, 1358044250)) << 1);
    			n = n << 1;
    			#else
    			// exp2 algorithm by Laurent de Soras
    			// https://www.musicdsp.org/en/latest/Other/106-fast-exp2-approximation.html
    			n = (n + 134217728) << 3;
    
    			n = multiply_32x32_rshift32_rounded(n, n);
    			n = multiply_32x32_rshift32_rounded(n, 715827883) << 3;
    			n = n + 715827882;
    			#endif
    			uint32_t scale = n >> (14 - ipart);
    			uint64_t phstep = (uint64_t)inc * scale;
    			uint32_t phstep_msw = phstep >> 32;
    			if (phstep_msw < 0x7FFE) {
    				ph += phstep >> 16;
    			} else {
    				ph += 0x7FFE0000;
    			}
    			phasedata[i] = ph;
    			Serial.println("freq");
    		}
    		release(freqModData);
    		release(phaseModData);
    	} else if (phaseModData && modulation_type == 1) {
    		// Phase Modulation
    		bp2 = phaseModData->data;
    		for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
    			// more than +/- 180 deg shift by 32 bit overflow of "n"
    		        uint32_t n = ((uint32_t)(*bp2++)) * phase_factor;
    			phasedata[i] = ph + n;
    			ph += inc;
    			Serial.println("phase");
    		}
    		release(freqModData);
    		release(phaseModData);
    	} else if (freqModData && phaseModData && modulation_type == 2) {
    		bp = freqModData->data;
    		bp2 = phaseModData->data;
    		for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
    			int32_t n = (*bp++) * modulation_factor; // n is # of octaves to mod
    		    uint32_t n2 = ((uint32_t)(*bp2++)) * phase_factor;
    			int32_t ipart = n >> 27; // 4 integer bits
    			n &= 0x7FFFFFF;          // 27 fractional bits
    			#ifdef IMPROVE_EXPONENTIAL_ACCURACY
    			// exp2 polynomial suggested by Stefan Stenzel on "music-dsp"
    			// mail list, Wed, 3 Sep 2014 10:08:55 +0200
    			int32_t x = n << 3;
    			n = multiply_accumulate_32x32_rshift32_rounded(536870912, x, 1494202713);
    			int32_t sq = multiply_32x32_rshift32_rounded(x, x);
    			n = multiply_accumulate_32x32_rshift32_rounded(n, sq, 1934101615);
    			n = n + (multiply_32x32_rshift32_rounded(sq,
    				multiply_32x32_rshift32_rounded(x, 1358044250)) << 1);
    			n = n << 1;
    			#else
    			// exp2 algorithm by Laurent de Soras
    			// https://www.musicdsp.org/en/latest/Other/106-fast-exp2-approximation.html
    			n = (n + 134217728) << 3;
    
    			n = multiply_32x32_rshift32_rounded(n, n);
    			n = multiply_32x32_rshift32_rounded(n, 715827883) << 3;
    			n = n + 715827882;
    			#endif
    			uint32_t scale = n >> (14 - ipart);
    			uint64_t phstep = (uint64_t)inc * scale;
    			uint32_t phstep_msw = phstep >> 32;
    			if (phstep_msw < 0x7FFE) {
    				ph += phstep >> 16;
    			} else {
    				ph += 0x7FFE0000;
    			}
    			phasedata[i] = ph + n2;
    			Serial.println("freqAndphase");
    		}
    		release(freqModData);
    		release(phaseModData);
    	}else {
    		// No Modulation Input
    		for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
    			phasedata[i] = ph;
    			ph += inc;
    		}
    	}
    Last edited by chuinst; 09-22-2021 at 05:21 AM. Reason: correct phaseAndfreq it should be freqAndphase

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •