Click here to Skip to main content
15,891,943 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
Hi,

I am developing one audio processing utility in Qt(C++), Now I can hear audio from speaker when I speak through mike, Now I need to apply echo effect to this audio output, How I can do this,I will get 16 bit audio samples in an integer array,what changes to this array will produce echo effect to output sound, Any examples or code will very helpful to me

Thanks in advance




Here is my code, I am using Qt as development tool

C#
void MainWindow::readMore()
{

    if(!m_audioInput)
        return;

    qint64 len = m_audioInput->bytesReady();
    if(len > 4096)
        len = 4096;

    qint64 l = m_input->read(m_buffer.data(), len);
    if(l > 0)
    {


        Q_ASSERT(m_format.sampleSize() % 8 == 0);
        const int channelBytes = m_format.sampleSize() / 8;
        const int sampleBytes = m_format.channels() * channelBytes;
        Q_ASSERT(len % sampleBytes == 0);
        const int numSamples = len / sampleBytes;

 short *data = (short*)m_buffer.data();
        addecho(data,numSamples,4000,0.9);
       // m_output->write(m_buffer);


    }



}

void MainWindow::addecho(short* pcm_databuffer,unsigned int pcm_datalength,unsigned int phase,double damping)
{
     std::vector<short> myvector;

  //int* pcm_databuffer_with_echo = new int[](pcm_datalength+phase);
  unsigned int i,j;
  for(i=0;i<phase;i++)
  {
      myvector.push_back(pcm_databuffer[i]);
   // pcm_databuffer_with_echo[i] = pcm_databuffer[i];
  }
  for(j=0;i<pcm_datalength;i++,j++)
  { myvector.push_back(pcm_databuffer[i] +(int)((double)pcm_databuffer[j]*damping));
   // pcm_databuffer_with_echo[i] = pcm_databuffer[i] +
    // (int)((double)pcm_databuffer[j]*damping);
  }
  for(;j<pcm_datalength;i++,j++)
  {
       myvector.push_back((int)((double)pcm_databuffer[j]*damping));
    //pcm_databuffer_with_echo[i] = (int)((double)pcm_databuffer[j]*damping);
  }

  // output to device
  short *data=(short *)myvector.data();
  m_output->write((char*)data, pcm_datalength+phase);
  //PumpToDevice(pcm_databuffer_with_echo,pcm_datalength+phase);

  //delete [] pcm_databuffer_with_echo;
   myvector.empty();
}
Posted
Updated 19-Sep-11 6:07am
v3

Little example for you. phase has to be calculated for the delay of your echo (sps*delay, i.e. 44000 samples per second * 0.5 seconds delay -> phase = 22000).
void addecho(int* pcm_databuffer,unsigned int pcm_datalength,unsigned int phase,double damping)
{
  int* pcm_databuffer_with_echo = new int[](pcm_datalength+phase);
  unsigned int i,j;
  for(i=0;i<phase;i++)>
  {
    pcm_databuffer_with_echo[i] = pcm_databuffer[i];
  }
  for(j=0;i<pcm_datalength;i++,j++)>
  {
    pcm_databuffer_with_echo[i] = pcm_databuffer[i] +
     (int)((double)pcm_databuffer[j]*damping);
  }
  for(;j<pcm_datalength;i++,j++)>
  {
    pcm_databuffer_with_echo[i] = (int)((double)pcm_databuffer[j]*damping);
  }

  // output to device
  PumpToDevice(pcm_databuffer_with_echo,pcm_datalength+phase);

  delete [] pcm_databuffer_with_echo;
}

Good luck.
 
Share this answer
 
Comments
Arun Kumar K S 19-Sep-11 2:56am    
Many thanks to your code. I used code like this I can hear sound but no echo in the output sound, My audio sample rate is 8000 so I called

addecho(data,numSamples,8000,0.9);
to

void MainWindow::addecho(short* pcm_databuffer,unsigned int pcm_datalength,unsigned int phase,double damping)
{
std::vector<short> myvector;

//int* pcm_databuffer_with_echo = new int[](pcm_datalength+phase);
unsigned int i,j;
for(i=0;i<phase;i++)
{
myvector.push_back(pcm_databuffer[i]);
// pcm_databuffer_with_echo[i] = pcm_databuffer[i];
}
for(j=0;i<pcm_datalength;i++,j++)
{="" myvector.push_back(pcm_databuffer[i]="" +(int)((double)pcm_databuffer[j]*damping));
="" pcm_databuffer_with_echo[i]="pcm_databuffer[i]" +
="" (int)((double)pcm_databuffer[j]*damping);
="" }
="" for(;j<pcm_datalength;i++,j++)
="" {
="" myvector.push_back((int)((double)pcm_databuffer[j]*damping));
="" }

="" output="" to="" device
="" short="" *data="(short" *)myvector.data();
="" m_output-="">write((char*)data, pcm_datalength+phase);
//PumpToDevice(pcm_databuffer_with_echo,pcm_datalength+phase);

//delete [] pcm_databuffer_with_echo;
myvector.empty();
}
mbue 19-Sep-11 5:39am    
You must send the resulting pcm-buffer to the output device inside this function. If you write it to a file use the correct buffer size. In the example above, i forgot, you have to check and adjust the sum for the 16-bit boundaries.
Regards.
Arun Kumar K S 19-Sep-11 6:56am    
I tried that (pcm_databuffer_with_echo,pcm_datalength+phase); to output device in that same function, I can hear the sound but no echo in output sound, What you mean by sum for the 16 bit boundaries, The only change I made in your code is to changed the integer array with vector because I am using a GCC compiler, GCC not supporting this type of declaration
mbue 19-Sep-11 9:08am    
I mean:
int sum = pcm_databuffer[i] +(int)((double)pcm_databuffer[j]*damping);
sum = min(sum,35535);
sum = max(sum,-35535);

because if your sound is realy loud, you get short overflows.
Perhaps you can post your original code as "improve question" so i can see your normal (without echo) wave output function.
Regards.
mbue 19-Sep-11 13:53pm    
I see the problem: youre writing a short array with array size of bytes. you need to write the array length multiplied by sizeof(short), thats the sizeof the buffer in bytes. therefore your output is cutted to the half of its real size. your pcm data has a maximal size of 4096 and your phase is 4000 -> the last 96 samples contains the echo and the remaining echo is cutted.
Regards.
It was hell finding a simple solution to this so i wrote my own and decided to post this here for future reference and for people to grab and be able to use quickly without all the hassle.

quick and dirty solution but it works.

happy effecting :)

C#
#define ECHO 1024*10
float echo_buffer[ECHO];
int echooffset=1024*2; // chenge to delay more example int echooffset=1024*6;
int echooffsetplay;
int EFFECT=1;


if (EFFECT)
{

    if (EFFECT==1) // reverb
{
            echo_buffer[echooffset]+=sample*0.5;// original *  ( amount of original )
            if (echooffset++>=ECHO-1)echooffset=0;
            sample+=echo_buffer[echooffsetplay];echo_buffer[echooffsetplay]*=0.45;// decay
            if (echooffsetplay++>=ECHO-1)echooffsetplay=0;
}
    if (EFFECT==2) // echo
{
            echo_buffer[echooffset]=sample*0.5;// original *  ( amount of original )
            if (echooffset++>=ECHO-1)echooffset=0;
            sample+=echo_buffer[echooffsetplay]*0.4;// amount to mix into dry
            if (echooffsetplay++>=ECHO-1)echooffsetplay=0;
}
    if (EFFECT==3) // spacial
{
            echo_buffer[echooffset]+=sample*0.5;// original *  ( amount of original )
            if (echooffset++>=ECHO-1)echooffset=0;
            sample-=echo_buffer[echooffsetplay];echo_buffer[echooffsetplay]*=0.45;// amount of spacial
            if (echooffsetplay++>=ECHO-1)echooffsetplay=0;
}


}
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900