Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-138834

Callback-based interface for QAudioSink and QAudioSource

XMLWordPrintable

    • Icon: Task Task
    • Resolution: Duplicate
    • Icon: P2: Important P2: Important
    • None
    • None
    • Multimedia
    • None
    • All

      Currently, we work with audio data through QIODevice, and the current use case is supposed to be used from the user thread.
      Advanced users often need to be able to access the underlying audio thread through a callback, so we're providing a new api for running QAudioSink/QAudioSource with a callback.
      We want to have the API type-safe: run a callback for the data type relevant to the underlying sample format. It means that for covering current formats, the callback should be a callable object with one of the signatures (might be extended later on).

      void(QSpan<int8_t>), void(QSpan<uint16_t>), void(QSpan<uint32_t>), void(QSpan<float>)
      

      Suggestions on how we can do so:

      1. 4 overloads

      void start(std::function<void(QSpan<int8_t>)> &&);
      void start(std::function<void(QSpan<int16_t>)> &&);
      void start(std::function<void(QSpan<int32_t>)> &&);
      void start(std::function<void(QSpan<float>)> &&);
      

      Pros:

      • Self-descriptive methods signatures
      • Straight-forward and simple.
      • Easy to add a new type

      Cons:

      • We already have 2 starts for pull/push mode; adding 4 ones makes the number of explicit overloads a bit excessive.
      • We should probably duplicate the documentation details for each method.

      2. std::variant

      using Callback = std::variant<
               std::function<void(QSpan<int8_t>)>,
               std::function<void(QSpan<int16_t>)>,
               std::function<void(QSpan<int32_t>)>,
               std::function<void(QSpan<float>)>
           >;
      void start(Callback &&);
      

      Pros:

      • One method with explicit type.

      Cons:

      • Hard to add a new type because of ABI.

      3. Template + private impl

      template <typename Callback>
      using if_audio_callback = std::enable_if_t</*check if the signature is proper*/, bool>;
      
      public:
      template <typename Callback, typename if_audio_callback<Callback> = true>
      void start(Callback &&callback)
      {
             startInternal({ std::forward<Callback>(callback) });
      }
      
      private:
      struct CallbackData 
      {
            std::variant<....> callback;
      };
      
      // pass the type only by ref to get around 
      void startInternal(CallbackData&& cbData);
      

      Pros:

      • Easy to add a new callback type
      • Documentation of the new start describes the calling consideration once. We just describe the signatures we can take. In other words, we get 3 starts for different purposes: QIDevice-pull, QIDevice-push, and audio thread callback.

      Cons:

      • It needs a private startInternal(CallbackData&&), and we have to support the private ABI. However, if we make CallbackData as a structure and pass it by ref, it should be easy.

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

            qtmultimediateam Qt Multimedia Team
            artemiy Artem Dyomin
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved:

                There are no open Gerrit changes