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.

What change should I make in attached .c file to give different output to left and right speaker ?

This is an example name task_audio in dsp 6713. What I want to give is two different output to left and right speaker. What change should I make ? Example code is written below as well as attached.Any help is appreciated.

/*
 *  Copyright 2003 by Texas Instruments Incorporated.
 *  All rights reserved. Property of Texas Instruments Incorporated.
 *  Restricted rights to use, duplicate or disclose this code are
 *  granted through contract.
 *  
 */
/* "@(#) DSP/BIOS 4.90.270 01-08-04 (bios,dsk6713-c04)" */
/* 
 *  ======== tsk_audio.c ========
 * 
 *  This example demonstrates the use of IOM drivers with SIOs and tasks by 
 *  using the DIO class driver with a user defined device mini-driver 
 *  called "codec" and a class driver DIO instance called "dio_codec". This is 
 *  the loopback application where audio is read from an input SIO, then sent 
 *  back via an output SIO.

 *  The following objects need to be created in the DSP/BIOS
 *  configuration for this application:
 *
 *  * A UDEV object, which links in a user device driver. In this
 *    case the UDEV is a codec based IOM device driver.
 *  * A DIO object, which links the UDEV object.
 *  * A TSK object, with the function to run set to the function echo
 *    defined in this file.
 *  * A LOG named trace for debug and status output.
 */

#include <std.h>

#include <log.h>
#include <sys.h>
#include <mem.h>
#include <sio.h>

#ifdef _6x_
extern far LOG_Obj trace;

/* 
 * Buffers placed in external memory are aligned on a 128 bytes boundary.
 * In addition, the buffer should be of a size multiple of 128 bytes for 
 * the cache work optimally on the C6x.
 */
#define BUFLEN 128      /* number of samples in the frame */
#define BUFALIGN 128    /* alignment of buffer to allow use of L2 cache */
#else
extern LOG_Obj trace;
#define BUFLEN 128      /* number of samples in the frame */
#define BUFALIGN 1
#endif

#define BUFSIZE (BUFLEN * sizeof(MdUns)) 

/* inStream and outStream are SIO handles created in main */
SIO_Handle inStream, outStream;

/* Function prototype */
static Void createStreams();
static Void prime();

/*
 * ======== main ========
 */
Void main()
{
    LOG_printf(&trace, "tsk_audio started");
}

/*
 * ======== createStreams ========
 */
static Void createStreams()
{
    SIO_Attrs attrs;
    
    /* align the buffer to allow it to be used with L2 cache */
    attrs = SIO_ATTRS;
    attrs.align = BUFALIGN;
    attrs.model = SIO_ISSUERECLAIM;

    /* open the I/O streams */
    inStream = SIO_create("/dioCodec", SIO_INPUT, BUFSIZE, &attrs);
    if (inStream == NULL) {
        SYS_abort("Create input stream FAILED.");
    }

    outStream = SIO_create("/dioCodec", SIO_OUTPUT, BUFSIZE, &attrs);
    if (outStream == NULL) {
        SYS_abort("Create output stream FAILED.");
    }
}

/*
 * ======== prime ========
 */
static Void prime()
{
    Ptr buf0, buf1, buf2, buf3;

    LOG_printf(&trace, "Allocate buffers started");

    /* Allocate buffers for the SIO buffer exchanges */
    buf0 = (Ptr)MEM_calloc(0, BUFSIZE, BUFALIGN);
    buf1 = (Ptr)MEM_calloc(0, BUFSIZE, BUFALIGN);
    buf2 = (Ptr)MEM_calloc(0, BUFSIZE, BUFALIGN);
    buf3 = (Ptr)MEM_calloc(0, BUFSIZE, BUFALIGN);
    if (buf0 == NULL || buf1 == NULL || buf2 == NULL || buf3 == NULL) {
        SYS_abort("MEM_calloc failed.");
    } 
    
    /* Issue the first & second empty buffers to the input stream */
    if (SIO_issue(inStream, buf0, SIO_bufsize(inStream), NULL) != SYS_OK) {
        SYS_abort("Error issuing buffer to the input stream");
    }
    if (SIO_issue(inStream, buf1, SIO_bufsize(inStream), NULL) != SYS_OK) {
        SYS_abort("Error issuing buffer to the input stream");
    }

    /* Issue the first & second empty buffers to the output stream */
    if (SIO_issue(outStream, buf2, SIO_bufsize(outStream), NULL) != SYS_OK) {
        SYS_abort("Error issuing buffer to the output stream");
    }
    if (SIO_issue(outStream, buf3, SIO_bufsize(outStream), NULL) != SYS_OK) {
        SYS_abort("Error issuing buffer to the output stream");
    }
}

/*
 * ======== echo ========
 * This function copies from the input SIO to the output SIO. You could
 * easily replace the copy function with a signal processing algorithm. 
 */
Void echo()
{
    Int i;
    Int nmadus;         /* number of minimal addressable units */
    MdUns *inbuf, *outbuf;

    /* Call createStream function to create I/O streams */
    createStreams();
    
    /* Call prime function to do priming */
    prime();

    /* Loop forever looping back buffers */
    for (;;) {
        /* Reclaim full buffer from the input stream */
        if ((nmadus = SIO_reclaim(inStream, (Ptr *)&inbuf, NULL)) < 0) {
            SYS_abort("Error reclaiming full buffer from the input stream");
        }

        /* Reclaim empty buffer from the output stream to be reused */
        if (SIO_reclaim(outStream, (Ptr *)&outbuf, NULL) < 0) {
            SYS_abort("Error reclaiming empty buffer from the output stream");
        }

        /* Do the data move. */
        for (i = 0; i < (nmadus / sizeof(short)); i++) {
            outbuf[i] = 100*inbuf[i];
        }

        /* Issue full buffer to the output stream */
        if (SIO_issue(outStream, outbuf, nmadus, NULL) != SYS_OK) {
            SYS_abort("Error issuing full buffer to the output stream");
        }

        /* Issue an empty buffer to the input stream */
        if (SIO_issue(inStream, inbuf, SIO_bufsize(inStream), NULL) != SYS_OK) {
            SYS_abort("Error issuing empty buffer to the input stream");
        }
    }
}

/*
 *  ======== prd10secs ========
 *  prd10secs is configured to be called every 10 seconds
 */
Void prd10secs()
{
    static Int seconds = 0;
    static Int minutes = 0;
    static Int hours = 0;

    seconds += 10;

    if (seconds == 60) {
        seconds = 0;
        minutes++;
        if (minutes == 60) {
            minutes = 0;
            hours++;
        }
        LOG_printf(&trace, "%d hours and %d minutes", hours, minutes);
    }
    else {
        LOG_printf(&trace, "%d seconds", seconds);
    }
}

 

/*
* Copyright 2003 by Texas Instruments Incorporated.
* All rights reserved. Property of Texas Instruments Incorporated.
* Restricted rights to use, duplicate or disclose this code are
* granted through contract.
*
*/
/* "@(#) DSP/BIOS 4.90.270 01-08-04 (bios,dsk6713-c04)" */
/*
* ======== tsk_audio.c ========
*
* This example demonstrates the use of IOM drivers with SIOs and tasks by
* using the DIO class driver with a user defined device mini-driver
* called "codec" and a class driver DIO instance called "dio_codec". This is
* the loopback application where audio is read from an input SIO, then sent
* back via an output SIO.

* The following objects need to be created in the DSP/BIOS
* configuration for this application:
*
* * A UDEV object, which links in a user device driver. In this
* case the UDEV is a codec based IOM device driver.
* * A DIO object, which links the UDEV object.
* * A TSK object, with the function to run set to the function echo
* defined in this file.
* * A LOG named trace for debug and status output.
*/

#include <std.h>

#include <log.h>
#include <sys.h>
#include <mem.h>
#include <sio.h>

#ifdef _6x_
extern far LOG_Obj trace;

/*
* Buffers placed in external memory are aligned on a 128 bytes boundary.
* In addition, the buffer should be of a size multiple of 128 bytes for
* the cache work optimally on the C6x.
*/
#define BUFLEN 128 /* number of samples in the frame */
#define BUFALIGN 128 /* alignment of buffer to allow use of L2 cache */
#else
extern LOG_Obj trace;
#define BUFLEN 128 /* number of samples in the frame */
#define BUFALIGN 1
#endif

#define BUFSIZE (BUFLEN * sizeof(MdUns))

/* inStream and outStream are SIO handles created in main */
SIO_Handle inStream, outStream;

/* Function prototype */
static Void createStreams();
static Void prime();

/*
* ======== main ========
*/
Void main()
{
LOG_printf(&trace, "tsk_audio started");
}

/*
* ======== createStreams ========
*/
static Void createStreams()
{
SIO_Attrs attrs;

/* align the buffer to allow it to be used with L2 cache */
attrs = SIO_ATTRS;
attrs.align = BUFALIGN;
attrs.model = SIO_ISSUERECLAIM;

/* open the I/O streams */
inStream = SIO_create("/dioCodec", SIO_INPUT, BUFSIZE, &attrs);
if (inStream == NULL) {
SYS_abort("Create input stream FAILED.");
}

outStream = SIO_create("/dioCodec", SIO_OUTPUT, BUFSIZE, &attrs);
if (outStream == NULL) {
SYS_abort("Create output stream FAILED.");
}
}

/*
* ======== prime ========
*/
static Void prime()
{
Ptr buf0, buf1, buf2, buf3;

LOG_printf(&trace, "Allocate buffers started");

/* Allocate buffers for the SIO buffer exchanges */
buf0 = (Ptr)MEM_calloc(0, BUFSIZE, BUFALIGN);
buf1 = (Ptr)MEM_calloc(0, BUFSIZE, BUFALIGN);
buf2 = (Ptr)MEM_calloc(0, BUFSIZE, BUFALIGN);
buf3 = (Ptr)MEM_calloc(0, BUFSIZE, BUFALIGN);
if (buf0 == NULL || buf1 == NULL || buf2 == NULL || buf3 == NULL) {
SYS_abort("MEM_calloc failed.");
}

/* Issue the first & second empty buffers to the input stream */
if (SIO_issue(inStream, buf0, SIO_bufsize(inStream), NULL) != SYS_OK) {
SYS_abort("Error issuing buffer to the input stream");
}
if (SIO_issue(inStream, buf1, SIO_bufsize(inStream), NULL) != SYS_OK) {
SYS_abort("Error issuing buffer to the input stream");
}

/* Issue the first & second empty buffers to the output stream */
if (SIO_issue(outStream, buf2, SIO_bufsize(outStream), NULL) != SYS_OK) {
SYS_abort("Error issuing buffer to the output stream");
}
if (SIO_issue(outStream, buf3, SIO_bufsize(outStream), NULL) != SYS_OK) {
SYS_abort("Error issuing buffer to the output stream");
}
}

/*
* ======== echo ========
* This function copies from the input SIO to the output SIO. You could
* easily replace the copy function with a signal processing algorithm.
*/
Void echo()
{
Int i;
Int nmadus; /* number of minimal addressable units */
MdUns *inbuf, *outbuf;

/* Call createStream function to create I/O streams */
createStreams();

/* Call prime function to do priming */
prime();

/* Loop forever looping back buffers */
for (;;) {
/* Reclaim full buffer from the input stream */
if ((nmadus = SIO_reclaim(inStream, (Ptr *)&inbuf, NULL)) < 0) {
SYS_abort("Error reclaiming full buffer from the input stream");
}

/* Reclaim empty buffer from the output stream to be reused */
if (SIO_reclaim(outStream, (Ptr *)&outbuf, NULL) < 0) {
SYS_abort("Error reclaiming empty buffer from the output stream");
}

/* Do the data move. */
for (i = 0; i < (nmadus / sizeof(short)); i++) {
outbuf[i] = 100*inbuf[i];
}

/* Issue full buffer to the output stream */
if (SIO_issue(outStream, outbuf, nmadus, NULL) != SYS_OK) {
SYS_abort("Error issuing full buffer to the output stream");
}

/* Issue an empty buffer to the input stream */
if (SIO_issue(inStream, inbuf, SIO_bufsize(inStream), NULL) != SYS_OK) {
SYS_abort("Error issuing empty buffer to the input stream");
}
}
}

/*
* ======== prd10secs ========
* prd10secs is configured to be called every 10 seconds
*/
Void prd10secs()
{
static Int seconds = 0;
static Int minutes = 0;
static Int hours = 0;

seconds += 10;

if (seconds == 60) {
seconds = 0;
minutes++;
if (minutes == 60) {
minutes = 0;
hours++;
}
LOG_printf(&trace, "%d hours and %d minutes", hours, minutes);
}
else {
LOG_printf(&trace, "%d seconds", seconds);
}
}

  • Manish,

    You should already be getting different outputs on the left and right output channels. If your two input channels are different from each other, then the two output channels will be different from each other, matching the inputs.

    I recommend you go to the training material we have on the TI Wiki Pages. Got here and search for "c6713 training" (no quotes) and look through the archived training material. The examples used are for audio applications, so the definition of the data stream will be included there.

    To prove this, change your copy loop to:

    Manish Kumar8 - revised said:
    /* Do the data move. */
    for (i = 0; i < (nmadus / sizeof(short)); i++) {
    outbuf[i] = 100*(i % 2)*inbuf[i];
    }

    Let me know if you hear a difference on the two output streams.

    Regards,
    RandyP

  • Thanks for your reply sir.

    If I got your code right , ain't you are giving zero o/p to one speaker and signal as input to other speaker ? I don't have DSP with me right now , Just confirming.

    if not then what I wanted was

    " I am giving audio input to both input channel through line in , But for output I want to send different amplitude let 2*input and 100*input , How to do that ?"

  • Well, this is a puzzle then.

    You correctly determined that one channel was getting zeroed out while the other channel was not. This means you recognized the order of samples in the buffers.

    Now, we need to find some method using the C language to make a decision identifying the channel, and then to apply a different gain value based on the result of that decision.

    You seem to be pretty good at reading the C code I wrote and not only figuring out the detail of what it is doing, but also you abstracted that to the higher-level concept of channels and their values. I am not sure how you will choose to do this new part. But I am confident you will choose wisely.

    Regards,
    RandyP

  • Well ! that trick seems to be working partially but still not completely.
    what is nmadus here for c6713 ? Its value seems to be more than 4*sizeof(short). 

    In our trick we are sending alternative short values in different channel but is it is the actual way ?

    How short values are passed to different channel of speaker ?

  • Manish,

    Manish Kumar8 said:
    that trick seems to be working partially but still not completely.

    You have not described what "that trick" is, so I cannot comment on your new code. You have not described what is working partially, nor what is not working completely, so again I cannot comment on your problem.

    Manish Kumar8 said:
    what is nmadus here for c6713 ? Its value seems to be more than 4*sizeof(short)

    It is a variable you declared that is assigned the return value from SIO_reclaim(). Please look to the documentation for the SIO_reclaim() function to find what its return value should be. I would assume it is much larger than 4_sizeof(short), so that is good.

    Manish Kumar8 said:

    In our trick we are sending alternative short values in different channel but is it is the actual way ?

    How short values are passed to different channel of speaker ?

    Please refer to the training material links mentioned above and to the documentation for the EVM and the SIO functions. The values are passed using the SIO_issue function, but I think you know that. If you want to understand the hardware better, please refer to the training material.

    Regards,
    RandyP