This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

HELP PLEASE

Other Parts Discussed in Thread: TLV320AIC23B

Hello people, i need help please,

Im using a TMS320C6713 DSK (spectrum digital) and my dvelopment enviorment is CCS v3.1.

My object is to aquire analog audio by the embedded codec tlv320aic23b, use McBSP1 to transfer the samples in the DSP,
filter the digital signal with an implemented IIR and then use again the codec to send out my new analog audio.

My IIR is full of decimal coefficents (like 0.5  0.003  etc).

The problem is that when i try to multiply my samples (the type i use to store my sample is Uint32, 32-bit unsigned int)
by decimal coefficents the output signal is very distorted.

example:

If i make a simple loopback with codec-McBSP there's no problem, i mean  take samples with codec and then send them back trough
the DAC of the codec without manipulate these samples.

If i multiply these samples by an integer (like 1, 2, 3....) there's no problem too.

But if i take these samples, that are 32-bit integers, and with casting i try to multiply by 0.5, for example, then if i send back
these new integer samples, the result audio is distorted, when the object was only to decrease the volume.

Instead of multiply by 0.5 i tryed to simply shift to the left my 32-bit-samples, but the distortion persists.

There's no problem if i shift to the right, that means multiply by 2, that is an integer coefficent again.

Here is my simple program that performs a loopback :  (please help me, i cant multiply my samples by non-integer numbers...WHY???)

----------------------------------------------------------------------------------------------------------

#include "dsk6713.h"
#include <csl.h>
#include "dsk6713_aic23.h"
#include <stdio.h>

#include "MyConfigDSPbioscfg.h"


void main()
{

    Uint32 sample, dxchannel, sxchannel, heyhomie=1;
    MCBSP_Config myMCBSPconf;

    DSK6713_AIC23_CodecHandle hCodec;

    DSK6713_AIC23_Config myConfAic={
            0x0117,  //adjust the left LINEinput volume.
        0x0117,  //adjust the right LINEinput volume.
        0x00FF,  //adjust the left Headphone volume.
        0x00FF,  //adjust the right Headphone volume.
        0x0012,  //AnalogAudioPathControl...enable the DAC, disable the Bypass, set the LINEinput as mine input instead of the micropone.
        0x0000,  //DigitalAudioPathControl...I don't know...
        0x0002,  //PowerDownControl...turn on the various things that i need, like DAC, ADC, etc..
        0x0043,  //DigitalAudioInterface...AIC = master mode, data format = DSP mode, lenght of a word = 16 bit, etc..
        0x0023,  //SamplingRateControl...i use USB mode so master clock is 12MHz, remaining bits are used to set the sample rate.
        0x0001   //DigitalInterfaceActivation...enable the interface.
    };

    DSK6713_init();
    CSL_init();
   
    hCodec=DSK6713_AIC23_openCodec(0,&myConfAic);

    MCBSP_getConfig(_MCBSP_hDev1,&myMCBSPconf);


    myMCBSPconf.rcr=0x1A0;  //McBSP works with one phase and one word (32 bits), in this way i can easily recognize left channel and right channel.(respectively first 16 bit and last 16 bits)
    myMCBSPconf.xcr=0x1A0;

    MCBSP_config(_MCBSP_hDev1,&myMCBSPconf);

    while(1){
       
        while(!MCBSP_rrdy(_MCBSP_hDev1)){
    }
    sample=MCBSP_read(_MCBSP_hDev1);

    rhchannel=sample&(0x0000FFFF);   // mask used to separate rhchannel to the lfchannel
    lfchannel=sample&(0xFFFF0000);

    //rhchannel>>=1; doesn't work
    //rhchannel=(float)(rhchannel*0.5);  doesn't work
       
    rhchannel*=1;  //if i multiply by integers simply the output volume is increased
    lfchannel*=1;
    sample=rhchannel|lfchannel;

    while(!MCBSP_xrdy(_MCBSP_hDev1)){
    }
    MCBSP_write(_MCBSP_hDev1,sample);
    }
}

I'VE CONNECTED THE AUDIO OUTPUT OF MY COMPUTER TO THE LINE-INPUT OF THE CODEC, AND A HEADPHONE ON THE HEADPHONE-OUTPUT OF THE CODEC.

WHEN THIS PROGRAM RUN I CAN HEAR MUSIC FROM MY COMPUTER USING THE HEADPHONE CONNECTED TO THE DSK BOARD. BUT IF I MULTIPLY SAMPLES BY

NON INTEGER VALUES THE AUDIO I HEARD BECOME VERY DISTORTED. I DON'T KNOW WHY !!!
IF SOMEONE WANT TO TRY THIS PROGRAM HE WILL NEED A CONFIGURATION DSP/BIOS FILE (.CDB), that in my progect it name is MyConfigDSPbios.cdb
I simply create that file choosing the dsk6713 config.file   seed  without modify it.

PLEASE HEEELLLPPPPPPPP
THANKS.

  • I don't know anything about you HW but I can comment on the code. Your code is just missing a few shifts. Assuming your samples are truly 16 bit unsigned values:

    Uint16 increase_by(Uint16 x, Uint16 n)
    {
      Uint32 y = x;              // Transfer to 32 bit register
      y *= n;                    // Multiply by n
      if(y > 0xFFFF) y = 0xFFFF; // Clip if larger than 16 bits.
      return((Uint16)y);         // Return 16 bits.
    }

    Uint16 decrease_by(Uint16 x, Uint16 n)
    {
      x /= n;     // Divide.
      return(x);  // Return 16 bits.
    }

    Uint32 sample_mul(Uint32 sample, Uint16 n)
    {
        Uint16 rhchannel;
        Uint16 lfchannel;

        rhchannel  = (Uint16)sample; // Extract right
        sample   >>= 16;             // Shift down the next value
        lfchannel  = (Uint16)sample; // Extract left

        rhchannel = increase_by(rhchannel, n);
        lfchannel = increase_by(lfchannel, n);

        sample   = lfchannel; // Left in bottom
        sample <<= 16;        // Shift up to upper
        sample  |= rhchannel; // Right in bottom.

        return(sample);
    }

    Uint32 sample_div(Uint32 sample, Uint16 n)
    {
        Uint16 rhchannel;
        Uint16 lfchannel;

        rhchannel  = (Uint16)sample; // Extract right
        sample   >>= 16;             // Shift down the next value
        lfchannel  = (Uint16)sample; // Extract left

        rhchannel = decrease_by(rhchannel, n);
        lfchannel = decrease_by(lfchannel, n);

        sample   = lfchannel; // Left in bottom
        sample <<= 16;        // Shift up to upper
        sample  |= rhchannel; // Right in bottom.

        return(sample);
    }
    ...
        while(1){
          
            while(!MCBSP_rrdy(_MCBSP_hDev1)){
        }
        sample=MCBSP_read(_MCBSP_hDev1);
    #if 1
        sample=sample_mul(sample,n);
    #else
        sample=sample_div(sample,n);
    #endif
        while(!MCBSP_xrdy(_MCBSP_hDev1)){
        }
        MCBSP_write(_MCBSP_hDev1,sample);
        }
    ...


    Slightly different if they are signed values. Not guarantees about the real time performance of multplys and divides.

     

  • Hello, its me again,
    unfortunately my problem remains.
    I've tried to use your functions but if i try to divide or multiply a channel by a non-integer number,
    even if i used "printf" to ensure that the modified channel was again an integer number, and it was,
    the output was distorted.
    Another problem is that, with your functions, if i use "sample_mul" to multiply rhchannel by 2 (integer)
    the distorsion remains.
    This doesn't happen if simply i multiply rhchannel in this way.....rhchannel*=2;

    Let me show you some examples ( rhchannel...lfchannel...is the same thing ):

    ...
    rhchannel*=2;  this works and the "right headphone" volume increase by 2
    lfchannel*=2;
    ...

    ...
    sample_mul(sample,2);   this make distortion on output and doesn't increase the volume
    ...

    ...
    rhchannel*=2.1;     this doesn't increase the "right headphone" volume, instead it make distortion on output
    ...

    ...
    rhchannel>>=1;      this doesn't divide by 2 the volume, instead it make distortion on output
    ...

    ...
    heyhomie=rhchannel;     the volume is increased
    heyhomie*=2;
    rhchannel=heyhomie;
    ...

    heyhomie=rhchannel;     this make distortion without decrease the "right headphone" volume
    heyhomie>>=1;
    rhchannel=heyhomie;
    ...

    Anyway, my sampling rate is 41 KHz, but i will need to 80 KHz, more or less.

    I don't know nothing about DSPs (i'm programming this DSK for a school project)
    but this problem is inexplicable, cos sometimes the program works good but sometimes not. Incredible!

    In fact, your code is right, and mine too.

    (maybe there's a problem in my DSP/BIOS config file, i didn't modify it, but it's strange that
     with integer numbers the program works,and with casting or simply shifting to the right there's
     a distortion on output)

    The things i said in the last post are still valid.

    Maybe, if you want, i can send you my folder where there's my project, but in this case i need an e-mail
    address where i'll be able to send the files.

    Please, take a look on this modified code, i used first your functions, then i tried an alternative method
    to make the division by two using only right shifts   ( <<= )..... incredibly the distortion persist....

    Thank you for your attention.
     


    #include "dsk6713.h"
    #include <csl.h>
    #include "dsk6713_aic23.h"
    #include <stdio.h>

    #include "MyConfigDSPbioscfg.h"

    Uint16 increase_by(Uint16 x, Uint16 n);
    Uint16 decrease_by(Uint16 x, Uint16 n);
    Uint32 sample_mul(Uint32 sample, Uint16 n);
    Uint32 sample_div(Uint32 sample, Uint16 n);



    void main()
    {

        Uint32 sample, rhchannel, lfchannel, heyhomie=0, findmask=1, i=15;
        MCBSP_Config myMCBSPconf;

        DSK6713_AIC23_CodecHandle hCodec;

        DSK6713_AIC23_Config myConfAic={
            0x0117,  //adjust the left LINEinput volume.
            0x0117,  //adjust the right LINEinput volume.
            0x00FF,  //adjust the left Headphone volume.
            0x00FF,  //adjust the right Headphone volume.
            0x0012,  //AnalogAudioPathControl...enable the DAC, disable the Bypass, set the LINEinput as mine input instead of the microphone.
            0x0000,  //DigitalAudioPathControl...I don't know...
            0x0002,  //PowerDownControl...turn on the various things that i need, like DAC, ADC, etc..
            0x0043,  //DigitalAudioInterface...AIC = master mode, data format = DSP mode, lenght of a word = 16 bit, etc..
            0x0023,  //SamplingRateControl...i use USB mode so master clock is 12MHz, remaining bits are used to set the sample rate.
            0x0001   //DigitalInterfaceActivation...enable the interface.
        };

        DSK6713_init();
        CSL_init();
       
        hCodec=DSK6713_AIC23_openCodec(0,&myConfAic);

        MCBSP_getConfig(_MCBSP_hDev1,&myMCBSPconf);
        myMCBSPconf.rcr=0x1A0;  //McBSP works with one phase and one word (32 bits), in this way i can easily recognize left channel and right channel.(respectively first 16 bit and last 16 bits)
        myMCBSPconf.xcr=0x1A0;

        MCBSP_config(_MCBSP_hDev1,&myMCBSPconf);

        findmask<<=31;     //use this for LOOP1

        //findmask<<=15;   //use this for LOOP2   

        while(1){
           
            while(!MCBSP_rrdy(_MCBSP_hDev1)){
        }
        sample=MCBSP_read(_MCBSP_hDev1);

        rhchannel=sample&(0x0000FFFF);
        lfchannel=sample&(0xFFFF0000);

        //heyhomie>>=1;                     doesn't work
        //heyhomie=(float)(heyhomie*0.5);   doesn't work
        //rhchannel/=2;                     doesn't work

    //LOOP1---------------------------------------------------------------------
    //       this loop1 divide by two rhchannel putting the result in heyhomie
    //       WITHOUT shift to the right any variable
           
        heyhomie=0;
        rhchannel<<=16;
        while(i>0){       // i starts from 15
            i--;
            heyhomie<<=1;
            if(rhchannel&findmask)
                heyhomie+=1;
            rhchannel<<=1;
        }
        i=15;

    //LOOP2---------------------------------------------------------------------
    //       this loop2 does the same thing that does loop1, without shift rxchannel
    //       but shifting to the right findmask
           
           
        //while(i>0){     // i starts from 15
        //    i--;
        //    heyhomie<<=1;
        //    if(rhchannel&findmask)
        //        heyhomie+=1;
        //    findmask>>=1;
        //}
        //i=15;
        //findmask<<=15;  

    //--------------------------------------------------------------------------        

        rhchannel=heyhomie;
       
        sample=rhchannel|lfchannel;


            //sample=sample_mul(sample,2);   Doesn't work.
       

        while(!MCBSP_xrdy(_MCBSP_hDev1)){
        }
        MCBSP_write(_MCBSP_hDev1,sample);
        }
    }

    Uint16 increase_by(Uint16 x, Uint16 n)
    {
      Uint32 y = x;              // Transfer to 32 bit register
      y *= n;                    // Multiply by n
      if(y > 0xFFFF) y = 0xFFFF; // Clip if larger than 16 bits.
      return((Uint16)y);         // Return 16 bits.
    }

    Uint16 decrease_by(Uint16 x, Uint16 n)
    {
      x /= n;     // Divide.
      return(x);  // Return 16 bits.
    }

    Uint32 sample_mul(Uint32 sample, Uint16 n)
    {
        Uint16 rhchannel;
        Uint16 lfchannel;

        rhchannel  = (Uint16)sample; // Extract right
        sample   >>= 16;             // Shift down the next value
        lfchannel  = (Uint16)sample; // Extract left

        rhchannel = increase_by(rhchannel, n);
        lfchannel = increase_by(lfchannel, n);

        sample   = lfchannel; // Left in bottom
        sample <<= 16;        // Shift up to upper
        sample  |= rhchannel; // Right in bottom.

        return(sample);
    }

    Uint32 sample_div(Uint32 sample, Uint16 n)
    {
        Uint16 rhchannel;
        Uint16 lfchannel;

        rhchannel  = (Uint16)sample; // Extract right
        sample   >>= 16;             // Shift down the next value
        lfchannel  = (Uint16)sample; // Extract left

        rhchannel = decrease_by(rhchannel, n);
        lfchannel = decrease_by(lfchannel, n);

        sample   = lfchannel; // Left in bottom
        sample <<= 16;        // Shift up to upper
        sample  |= rhchannel; // Right in bottom.

        return(sample);
    }

  • Are you sure the samples are unsigned?

     

  • Ok,

    now that you've said that     im not quite sure.

    I'm not alone in this project so i am going to ask my partner tomorrow.

    Tomorrow we'll try to consider those samples like signed values, and then

    i'll answer you.

  • Assuming a signed 16-bit 2s complement format:

    Int16 increase_by(Int16 x, Uint16 n)
    {
      Int32 y = x;              // Transfer to 32 bit register

      y *= n;                    // Multiply by n

      if(y > 32767)
        y = 32767;  // Clip if larger than 16 bits.
      else if(y < -32768)
        y = -32768; // Clip if larger than 16 bits.

      return((Int16)y);         // Return 16 bits.
    }

    Int16 decrease_by(Int16 x, Uint16 n)
    {
      x /= n;     // Divide.
      return(x);  // Return 16 bits.
    }

    /* Assumes sample consists of two 16 bit signed 2-complement values. */
    void breakout_channels(Uint32 sample, Int16 *left, Int16 *right)
    {
        Uint16 temp;

        temp       = (Uint16)sample; // Extract right
       *right      = (Int16)temp;    // Reinterpet as signed and save
        sample   >>= 16;             // Shift down the next value
        temp       = (Uint16)sample; // Extract Left
       *left       = (Int16)temp;    // Reinterpet as signed and save
    }

    /* Assumes sample consists of two 16 bit signed 2-complement values. */
    Uint32 combine_channels(Int16 left, Int16 right)
    {
        Uint32 sample;
        Uint16 temp16;

        temp16   = (Uint16)left; // Reinterpret as unsigned.
        sample   = temp16;       // Left in bottom
        sample <<= 16;           // Shift up to upper
        temp16   = (Uint16)right;// Reinterpret as unsigned.
        sample  |= temp16;       // Right in bottom.
        return(sample);
    }

    Uint32 sample_mul(Uint32 sample, Uint16 n)
    {
        Int16 rhchannel;
        Int16 lfchannel;

        breakout_channels(sample, &lfchannel, &rhchannel);

        rhchannel = increase_by(rhchannel, n);
        lfchannel = increase_by(lfchannel, n);

        sample = combine_channels(lfchannel, rhchannel);

        return(sample);
    }

    Uint32 sample_div(Uint32 sample, Uint16 n)
    {
        Int16 rhchannel;
        Int16 lfchannel;

        breakout_channels(sample, &lfchannel, &rhchannel);

        rhchannel = decrease_by(rhchannel, n);
        lfchannel = decrease_by(lfchannel, n);

        sample = combine_channels(lfchannel, rhchannel);

        return(sample);
    }

    If you have an unsigned PCM format then you have shift the values down by half full scale.

    /* Assumes sample consists of two 16 bit unsigned values and */
    /* analog 0 is 0x8000 */
    void breakout_channels(Uint32 sample, Int16 *left, Int16 *right)
    {
        Uint16 temp;

        temp       = (Uint16)sample; // Extract right
       *right      = temp-0x8000;    // Move down and save
        sample   >>= 16;             // Shift down the next value
        temp       = (Uint16)sample; // Extract Left
       *left       = temp-0x8000;    // Move down and save
    }

    /* Assumes sample consists of two 16 bit unsigned values and */
    /* analog 0 is 0x8000 */
    Uint32 combine_channels(Int16 left, Int16 right)
    {
        Uint32 sample;
        Uint16 temp16;

        temp16   = (Uint16)left;   // Reinterpret as unsigned.
        sample   = (temp16+0x8000);// Left in bottom
        sample <<= 16;             // Shift up to upper
        temp16   = (Uint16)right;  // Reinterpret as unsigned.
        sample  |= (temp16+0x8000);// Right in bottom.
        return(sample);
    }

  • Hello, Mr. Wong
    i need to say "THANK YOU VERY MUCH".
    You were right, that samples are signed values, and your functions work good.
    My partner has said you are a big BOSS. I agree.

    (maybe i'll need help again in future, i'll post here if there's no problems)

    (rereading my posts i've realized i've written "right shift" instead of "left sh." and viceversa.
     I apologize if this has created confusion hehe :)   )

    Thanks again for your quick replies,

    goodbye,

    Olsen.