Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. pumping audio on a background thread, not a timer?
Forum Updated to NodeBB v4.3 + New Features

pumping audio on a background thread, not a timer?

Scheduled Pinned Locked Moved Solved General and Desktop
5 Posts 2 Posters 524 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Offline
    D Offline
    davecotter
    wrote on last edited by davecotter
    #1

    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?

    jsulmJ 1 Reply Last reply
    0
    • D Offline
      D Offline
      davecotter
      wrote on last edited by davecotter
      #5

      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.

      1 Reply Last reply
      1
      • D davecotter

        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?

        jsulmJ Offline
        jsulmJ Offline
        jsulm
        Lifetime Qt Champion
        wrote on last edited by
        #2

        @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.

        https://forum.qt.io/topic/113070/qt-code-of-conduct

        1 Reply Last reply
        1
        • D Offline
          D Offline
          davecotter
          wrote on last edited by davecotter
          #3

          (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?

          1 Reply Last reply
          0
          • D Offline
            D Offline
            davecotter
            wrote on last edited by davecotter
            #4

            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

            1 Reply Last reply
            0
            • D Offline
              D Offline
              davecotter
              wrote on last edited by davecotter
              #5

              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.

              1 Reply Last reply
              1

              • Login

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • Users
              • Groups
              • Search
              • Get Qt Extensions
              • Unsolved