Adding specific frequencies to the signal by addtive synthesis

Hi!
So I want to add some specific frequencies to the guitar signal. I m trying to achive this by adding some sinus to the signal. I have done fft on guitar A4 note to find out that the fundamental frequency is 440 Hz and the rest of frequencies are multiples of it ----> harmonics (880 1320 etc…) and i want to add to this signal 220, 660, 1100, 1540 Hz by addtive synthesis. So I want to add 220 Hz and multiples of it, I know that there are gonna be frequencies that are already in sound, but what i really care is to add 220, 660, 1100, 1540 Hz to the signal. So how I m able to add those dissired frequencies to the signal and also control amplitude of them.

This is how i add one freq to the signal.

for (int s = 0; s < buffer.getNumSamples(); s++)
        {
            updateAngleDelta(roundedFreqToAdd);
            auto currentSample = (float)std::sin(currentAngle);
            currentAngle += angleDelta;
            channelData_0[s] += currentSample * rms/10;
        }

Thanks in advance!

I think this has many problems to solve that are not trivial, for example keeping the envelope of the original harmonic, it would also have to be in the same phase otherwise it will cancel. And also the harmonics are usually a varied combination of the same harmonic which produces oscillations or resonances, And you have to take into account the greater inharmonicity in some notes, pitch changes, vibratos… There are many things to reproduce more than a simple sine wave with fixed volume and frequency.

What if you first try modifying the gain of the harmonics in the frequency domain which is just a multiplication? This would also allow you to attenuate them. You could use a windowing function in a range of several hertz around those harmonics that has less effect on the sides to make sure that the whole harmonic is amplified.

Thank you for your response! So i have tried to do it in frequency domain. What I did: do FFT, get fundamental frequency, find bins with frequencies i want to boost and multiple magnitude of it. So i was able to boost harmonics that i have in signal. But i couldnt add new frequencies to the signal. Maybe i did something wrong, here is my code :

   for (int s = 0; s < buffer.getNumSamples(); s++)
    {
        float currentSample = channelData_0[s];

        if (fifoIndex == buffer.getNumSamples())
        {
            std::fill(fftData.begin(), fftData.end(), 0.0f);
            std::fill(fifo.begin() + fifoIndex, fifo.end(), 0.f);
            std::copy(fifo.begin(), fifo.end(), fftData.begin());
            my_FFT.performRealOnlyForwardTransform(fftData.data());
      
            fifoIndex = 0;


            /// complex ----> magnitude ///
            int magPlace = 0;
            std::fill(magnitudeData.begin(), magnitudeData.end(), 0.0f);
            for (int i = 0; i < fftData.size(); i += 2)
            {
                float magnitude = 0;
                magnitude = getMagnitude(fftData[i], fftData[i + 1]);
                magnitudeData[magPlace] = magnitude;
                magPlace++;
            }

            /// get fundamental freq /// 
            max = 0;
            idx = 0;
            for (int i = 0; i < magnitudeData.size(); i++)
            {

                float potMaxMagnitude = magnitudeData[i];
                if (max < potMaxMagnitude)
                {
                    max = potMaxMagnitude;
                    idx = i;
                }
            }
         
            

                _RPT1(0, "idx %d\n", idx);
                fundamentalFreq = (idx * m_sampleRate) /fftData.size(); 
                _RPT1(0, "Fundamental_Freq1 %.6f\n", fundamentalFreq);
           
                
                    /// boosting /// 
                    int countNonHar = 1;
                    int countHar = 2;
                    for (int i = 0; i < (multiVariables.size() - 1); i++)   //// zmiana  for (int i = 0; i < (multiVariables.size() - 1); i++)  
                    {


                        /// freq x1.5,x2.5 x3.5 ....

                        magnitudeData[(idx * countNonHar) + (idx / 2)] = TestMultiVariables[i]; 
                        magnitudeData[((magnitudeDataSize ) - (idx * countNonHar) + (idx / 2))-1] = TestMultiVariables[i];
                        //countNonHar++;

                        // freq x2,x3,x4,x5...

                        magnitudeData[idx * countHar] *= TestMultiVariables[i]; 
                        magnitudeData[((magnitudeDataSize) - (idx * countHar))-1] *= TestMultiVariables[i];
                        countHar++;
                    }


                    for (int i = 0; i < freqToBoost.size(); i++)
                    {
                        int bin = freqToBoost[i] * magnitudeDataSize / m_sampleRate;
                        _RPT1(0, "660 bin %d\n", bin);
                        magnitudeData[bin] = 5;
                        magnitudeData[(magnitudeDataSize-1) - bin] = 5;
                    }

                    /// magnitude ----> real,image,real.... /// 
                    int fftIndex = 0;
                    for (int i = 0; i < magnitudeDataSize; i++)
                    {

                        /// phase/// 

                        std::complex <float> complexNumber(fftData[fftIndex], fftData[fftIndex + 1]);
                        float phase = std::arg(complexNumber);

                        /// real and imag ///
                        float real = magnitudeData[i] * std::cos(phase);
                        float imag = magnitudeData[i] * std::sin(phase);

                        /// fftData changing 
                        fftData[fftIndex] = real;
                        fftData[fftIndex + 1] = imag;
                        fftIndex += 2;
                    }


                    //// inverse FFT
                    my_FFT.performRealOnlyInverseTransform(fftData.data());

                

        }
        double window = 0.5 * (1 -std::cos(2 * m_Pi * s / (buffer.getNumSamples() - 1)));
        float windowAmp = std::sin(float(fifoIndex) * sizeMaxInvPi);
        fifo[fifoIndex] = currentSample* window;
        ++fifoIndex;

}

I don’t know what’s going on, but as I said before it could be the case of adding a harmonic with the reverse phase and canceling the original.

On a guitar all harmonics are audible, so you could amplify it as much as necessary.

You can see that harmonics are not single frequencies that’s why I said to check and amplify with a window function around the harmonic, the window could be about the size of the fundamental frequency.

You can also see that it is not necessarily always the fundamental that is the loudest, over the course of the note it could even be much lower. one way to confirm the fundamental is by the distance between harmonics which should be very close to the fundamental.

Hi! Thanks for your tips.

So I understand that

and i was able to do that. My goal is : for example I play sound 440 Hz so its sound A4 and thats how frequency analysis of it looks like:

So i can see that all sound components are multiples of fundamental frequency = those are harmonics. But what i really want to do to add to this concrete sound a frequencies which are multiples of 220 Hz so my plot of FFT would look like this:

So line red represents a guitar sound A4 and the green one is what i want to get. I know that the amplitude of 220 Hz 660 Hz is realy small (in green plot), but the rest of the multiples of 220 Hz frequency have higher amplitude like 1540 Hz 1980 Hz and so on.

What about trying to pitch shift sound to half of its pitch. So when I play sound A4 - 440 Hz i will pitch shift it to 220 Hz and after that I will be able to control the amplitude of all harmonics of 220 Hz and the add it to the input signal?

I apologize for any misunderstandings on my part. It s my first project in juce and DSP.

Thanks in advance!

theoretically if you halve the pitch and remove the fundamental you will have those intermediate harmonics, but you would have to amplify the original harmonics to keep the harmonic series. just experiment.