Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

pumping audio on a background thread, not a timer?



  • i have a cross platform (mac / win) app that plays audio.
    i'm using the push method for audio PCM
    instead of using a timer, i'm just running the pump on a background thread.

    This works fine on mac, but produces silence on windows.

    is this... a limitation?

    the thread object:

    class CT_AudioRender : public QThread
    {
    	//Q_OBJECT
    	typedef QThread	_inherited;
    	CAudioUnitChain		*thiz;
    	QIODevice			*i_outP;
    	CAudioUnit			*i_auP;
    
    	public:
    	CT_AudioRender(CAudioUnitChain *in_thiz) :
    		_inherited(),
    		thiz(in_thiz),
    		i_outP(NULL),
    		i_auP(in_thiz->GetCUnit_Out())
    	{
    		setObjectName("CT_AudioRender");
    		start(QThread::HighPriority);
    	}
    
    	void run() override
    	{
    		SetUpThread();
    		i_auP->Start(&i_outP);
    		IX(thiz->render(i_outP));
    		i_auP->Stop();
    		thiz->i_stopped.signal();
    	}
    };
    

    the pump:

    void	CAudioUnitChain::render(QIODevice *ioP)
    {
    	CAudioUnit		*auP = GetCUnit_Out();
    	QAudioOutput	*audioOutput(auP->i_qGeneratorP->i_qOutputP.get());
    	QByteArray		buffer(32768, 0);
    	//CAudioPlayer	*playerP((CAudioPlayer *)auP->i_source.inputProcRefCon);
    
    	do {
    		if (audioOutput->state() != QAudio::StoppedState) {
    			int		chunks = audioOutput->bytesFree() / audioOutput->periodSize();
    
    			while (chunks--) {
    				qint64	len = 0;
    
    				len = auP->i_qGeneratorP->read(buffer.data(), audioOutput->periodSize());
    
    				if (len) {
    					ioP->write(buffer.data(), len);
    				}
    
    				if (len != audioOutput->periodSize()) {
    					break;
    				}
    			}
    		}
    
    		MPDelay(0.002);
    	} while (!i_doneB.Get());
    }
    

    Am I missing something critical?



  • a user suggested i make a minimum compileable example. and in doing so, i ironed out my problem. i'm now able to do both push and pull on a background thread

    if you'd like to see how to properly do audio on a background thread, see the example in this post. note the bug i'm trying to fix in THAT post means the buttons in the UI don't update, but the audio example does in fact work.


  • Lifetime Qt Champion

    @davecotter Please post your code as text, not pictures.
    You should initialise your members in run() if you want to use them in your thread. Currently you're doing this in constructor. QThread instance itself lives in the old thread.



  • (fixed pic to text, I liked the pic cuz it preserves syntax coloring and formatting (why are tabs 8 spaces?) )

    To be clear: I'm not  initting any Qt objects in the constructor, that all  happens inside therun()function, in thei_auP->Start(&i_outP);call.

    Specifically: bothi_qGeneratorPandi_qOutputPare allocated there. I think they're the only Qt objects use within the new thread?

    Is there some other object you think is being cross-thread abused?
    You mention the QThread object itself? I don't see where I'm incorrectly using that in the new thread?

    notes:
    on the back thread, i do interact with QAudioDeviceInfo::availableDevices(), which was already initted, probably on the main thread, is this a problem?



  • anyone else have any ideas?

    is it possible i'm just using QThread wrong? and it HAPPENS to work fine on mac but fails on windows?

    is this blogger really revealing the ONE TRUE NATURE of QThread:
    https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/

    ?

    -dave



  • a user suggested i make a minimum compileable example. and in doing so, i ironed out my problem. i'm now able to do both push and pull on a background thread

    if you'd like to see how to properly do audio on a background thread, see the example in this post. note the bug i'm trying to fix in THAT post means the buttons in the UI don't update, but the audio example does in fact work.


Log in to reply