libsox effects chain: sample rate is "lost"

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

libsox effects chain: sample rate is "lost"

Benjamin-63
Hi,

I have built an effects chain with the following effects
- my custom input
- speed
- my custom output

The chain runs, but the output is identical to the input.
I debugged around and found out that the speed sees a sample rate of 0!

For the input effect I gave a signal info to sox_add_effect that has 48000
as sample rate, but for all further I gave SOX_UNSPECIFIED because I assume
that the effects chain will know the correct values from the previous
effect. I did so, because some effects change sample rate or channels and my
class wouldn't know.

I am still new to sox programming and maybe I missed something.
Does someone have a hint for me?

Best regards
Benjamin

P.S. I attach the source code of the sox thread, in case I missed to explain
something.

#include "soxthread.h"
#include "tools.h"
#include <QDebug>
#include <QThreadStorage>

#define EMSG_CREATEEFFECT trUtf8("Konnte SoX-Effekt \"%1\" nicht initialisieren")
#define EMSG_EFFECTPARAMS trUtf8("Fehlerhafte Parameter für SoX-Effekt \"%1\"")
#define EMSG_ADDEFFECT trUtf8("Konnte Effekt nicht der Effektkette hinzufügen")

/*============================================================================
        internal input/output effects for the sox effect chain
  ============================================================================*/

typedef struct {
        TSRingBuffer<int16_t> *b;
} privdata_t;


/* data for sox init, use mutex! */
TSRingBuffer<int16_t>* inbuffer;
TSRingBuffer<int16_t>* outbuffer;
/** SoxInitMutex
  used for sox_init()/sox_quit() calls as well as the initialization of the
  sox effects chain(s)
  */
QMutex SoxInitMutex;
/* **** */

/* ==== The input effect ==== */
extern "C" int input_getopts(sox_effect_t * effp, int argc UNUSED, char *argv[] UNUSED)
{
        privdata_t *p = (privdata_t*)effp->priv;
        p->b = inbuffer;
        return SOX_SUCCESS;
}

extern "C" int input_drain(sox_effect_t * effp, sox_sample_t *obuf, size_t *osamp)
{
        privdata_t *p = (privdata_t*)effp->priv;
        /* ensure that *osamp is a multiple of the number of channels. */
        *osamp -= *osamp % effp->out_signal.channels;

        /* Read up to *osamp samples into obuf; store the actual number read
        * back to *osamp */
        int16_t *tbuf = new int16_t[*osamp];
        while (!p->b->isEof())
        {
                unsigned read = p->b->get(tbuf, *osamp);
                if (read == 0)
                        Delay::msleep(10);
                else
                {
                        for (size_t i = 0; i < *osamp; i++)
                        {
                                obuf[i] = SOX_SIGNED_16BIT_TO_SAMPLE(tbuf[i],);
                        }
                        break;
                }
        }
        delete[] tbuf;
        if (p->b->isEof())
                return SOX_EOF;
        else
                return SOX_SUCCESS;
}

sox_effect_handler_t *input_effect()
{
        static sox_effect_handler_t effect = {
                "bufferinput", "internal effect", SOX_EFF_MCHAN,
                input_getopts, NULL, NULL, input_drain, NULL, NULL, sizeof(privdata_t)
        };
        return &effect;
}


/* ==== The output effect ==== */
extern "C" int output_getopts(sox_effect_t * effp, int argc UNUSED, char *argv[] UNUSED)
{
        privdata_t *p = (privdata_t*)effp->priv;
        p->b = outbuffer;
        return SOX_SUCCESS;
}

extern "C" int output_flow(sox_effect_t *effp, const sox_sample_t *ibuf,
                                           sox_sample_t *obuf UNUSED, size_t *isamp, size_t *osamp)
{
        if (*isamp == 0) //nothing to do?
                return SOX_SUCCESS;

        privdata_t *p = (privdata_t*)effp->priv;
        SOX_SAMPLE_LOCALS;
        *osamp = 0;
        int16_t *tbuf = new int16_t[*isamp];
        int clips;
        for (size_t i = 0; i < *isamp; i++)
        {
                tbuf[i] = SOX_SAMPLE_TO_SIGNED_16BIT(ibuf[i], clips);
        }
        size_t pos = 0;
        while (pos < *isamp)
        {
                size_t len = qMin<size_t>(*isamp-pos, p->b->getFree());
                if (len == 0)
                {
                        Delay::msleep(10);
                        continue;
                }
                if (!p->b->put(tbuf+pos, len))
                {
                        delete[] tbuf;
                        return SOX_EOF;
                }
                pos += len;
        }
        delete[] tbuf;
        return SOX_SUCCESS;
}

sox_effect_handler_t *output_effect()
{
        static sox_effect_handler_t effect = {
                "bufferoutput", "internal effect", SOX_EFF_MCHAN,
                output_getopts, NULL, output_flow, NULL, NULL, NULL, sizeof(privdata_t)
        };
        return &effect;
}



/*============================================================================
        SoxThread class
  ============================================================================*/

namespace FREAKS
{
int sox_usage = 0;

SoxThread::SoxThread(
                TSRingBuffer<int16_t> *inBuffer, TSRingBuffer<int16_t> *outBuffer,
                int sampleRate, int channels, QObject *parent
                )
                : QThread(parent)
{
        {
                QMutexLocker l(&SoxInitMutex);
                if (sox_usage == 0)
                        sox_init();
                sox_usage++;
        }
        ib = inBuffer;
        ob = outBuffer;
        splRate = sampleRate;
        ch = channels;

        sox_encodinginfo_t ei = {
                SOX_ENCODING_SIGN2, SOX_SAMPLE_PRECISION, 0.0,
                SOX_OPTION_DEFAULT, SOX_OPTION_DEFAULT, SOX_OPTION_DEFAULT, sox_false
        };
        chain = sox_create_effects_chain(&ei, &ei);
}

SoxThread::~SoxThread()
{
        sox_delete_effects_chain(chain);
        {
                QMutexLocker l(&SoxInitMutex);
                sox_usage--;
                if (sox_usage == 0)
                        sox_quit();
        }
}

void SoxThread::addEffect(QString name, QStringList &args)
{
        EffectData ed = { name, args };
        effects << ed;
}

bool SoxThread::doAddEffect(QString &name, QStringList &args)
{
        //create effect
        sox_effect_t *e = sox_create_effect(sox_find_effect(name.toLocal8Bit()));
        if (!e)
        {
                error(EMSG_CREATEEFFECT.arg(name));
                return false;
        }

        //copy arguments into C-style array
        char **argv;
        argv = new char*[args.count()];
        for (int i = 0; i < args.count(); i++)
        {
                QString s = args[i];
                argv[i] = qstrcpy((char*)malloc(s.length()+1), s.toLocal8Bit());
        }
        //send args to effect
        int r = sox_effect_options(e, args.count(), argv);

        //free arguments
        for (int i = 0; i < args.count(); i++)
        {
                free(argv[i]);
        }
        delete[] argv;

        if (r != SOX_SUCCESS)
        {
                sox_delete_effect(e);
                error(EMSG_EFFECTPARAMS.arg(name));
                return false;
        }

        //add effect to the effect chain
        sox_signalinfo_t si = {
                SOX_UNSPEC, SOX_UNSPEC, 32, SOX_UNSPEC, SOX_UNSPEC
        };

        r = sox_add_effect(chain, e, &si, &si);
        if (r != SOX_SUCCESS)
        {
                sox_delete_effect(e);
                error(EMSG_ADDEFFECT);
                return false;
        }
        return true;
}//doAddEffect()

void SoxThread::addInputEffect()
{
        sox_signalinfo_t si = {
                splRate, ch, 32, SOX_UNSPEC, NULL
        };

        sox_effect_t *e = sox_create_effect(input_effect());
        sox_effect_options(e, 0, NULL);
        sox_add_effect(chain, e, &si, &si);
}

void SoxThread::addOutputEffect()
{
        sox_signalinfo_t si = {
                splRate, ch, 32, SOX_UNSPEC, SOX_UNSPEC
        };

        sox_effect_t *e = sox_create_effect(output_effect());
        sox_effect_options(e, 0, NULL);
        sox_add_effect(chain, e, &si, &si);
}

void SoxThread::run()
{
        //add effects to the effects chain
        {
                QMutexLocker l(&SoxInitMutex);
                inbuffer = ib;
                outbuffer = ob;
                addInputEffect();
                foreach(EffectData ef, effects)
                {
                        if (!doAddEffect(ef.name, ef.params))
                                return;
                }
                addOutputEffect();
        }

        //let sox do all the work ;-)
        sox_flow_effects(chain, NULL, NULL);

        //delete effects from the effects chain
        sox_delete_effects(chain);

        //let other threads know that there will be no more data
        ib->setEof(true);
        ob->setEof(true);
}


}//namespace

------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
Sox-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/sox-users
Reply | Threaded
Open this post in threaded view
|

Re: libsox effects chain: sample rate is "lost"

Rob Sykes
At the moment, adding of the rate effect as necessary is handled outside libSoX.  Have a look at example3.c in the SoX source distribution for how this can be done.

HTH,
Rob

--- On Sun, 18/10/09, Benjamin <[hidden email]> wrote:
> I have built an effects chain with the following effects
> - my custom input
> - speed
> - my custom output
>
> The chain runs, but the output is identical to the input.
> I debugged around and found out that the speed sees a
> sample rate of 0!



     

------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
Sox-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/sox-users
Reply | Threaded
Open this post in threaded view
|

Re: libsox effects chain: crash (was: sample rate is "lost")

Benjamin-63
Thanks for your patience with me :-)
I added a rate affect, as well as tried the tempo effect, but now there is a
different problem: SEGV in sox_flow_effects.

It seems as if the function tried to go beyond the end of my effect chain.
Is this a bug or, again, my fault?

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x40d41950 (LWP 20465)]
0x00007f5ec8fac09e in sox_flow_effects (chain=0x7761c0, callback=0,
    client_data=0x0) at effects.c:345
345         size_t osize = chain->effects[e][0].oend -
chain->effects[e][0].obeg;
Current language:  auto; currently c
(gdb) print *chain
$1 = {effects = {0x782c50, 0x79d170, 0x806520, 0x0 <repeats 17 times>},
  length = 3, ibufc = 0x68f7a0, obufc = 0x68f7c0, global_info = {
    plot = sox_plot_off, global_info = 0x7f5ec925afe0}, in_enc = 0x41cb7b30,
  out_enc = 0x41cb7b30}
(gdb) print e
$2 = 3
(gdb) bt
#0  0x00007f5ec8fac09e in sox_flow_effects (chain=0x7761c0, callback=0,
    client_data=0x0) at effects.c:345
#1  0x0000000000418064 in FREAKS::SoxThread::run (this=0x41cb7c70)
    at soxthread.cpp:247
#2  0x00007f5ec8234354 in ?? () from /usr/lib/libQtCore.so.4
#3  0x00007f5ec7fcb3f7 in start_thread () from /lib/libpthread.so.0
#4  0x00007f5ec75a0b4d in clone () from /lib/libc.so.6
#5  0x0000000000000000 in ?? ()
(gdb) q


Basically I call the sox functions in the following order:
sox_init()
sox_create_effects_chain()
LOOP:
        sox_create_effect()
        sox_effect_options()
        sox_add_effect()
sox_flow_effects() <--- *bang*


robs schrieb:

> At the moment, adding of the rate effect as necessary is handled outside libSoX.  Have a look at example3.c in the SoX source distribution for how this can be done.
>
> HTH,
> Rob
>
> --- On Sun, 18/10/09, Benjamin <[hidden email]> wrote:
>> I have built an effects chain with the following effects
>> - my custom input
>> - speed
>> - my custom output
>>
>> The chain runs, but the output is identical to the input.
>> I debugged around and found out that the speed sees a
>> sample rate of 0!
>
>
>
>      
>
> ------------------------------------------------------------------------------
> Come build with us! The BlackBerry(R) Developer Conference in SF, CA
> is the only developer event you need to attend this year. Jumpstart your
> developing skills, take BlackBerry mobile applications to market and stay
> ahead of the curve. Join us from November 9 - 12, 2009. Register now!
> http://p.sf.net/sfu/devconference
> _______________________________________________
> Sox-users mailing list
> [hidden email]
> https://lists.sourceforge.net/lists/listinfo/sox-users
>
>

------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
Sox-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/sox-users