Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. International
  3. German
  4. Zugriff auf Methoden anderer Klassen
Forum Update on Monday, May 27th 2025

Zugriff auf Methoden anderer Klassen

Scheduled Pinned Locked Moved Unsolved German
16 Posts 5 Posters 1.2k Views
  • 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.
  • M MHage

    Hallo,

    In meinem aktuellen Projekt möchte ich Audio Dateien aufnehmen. In dem offiziellen example "Audiorecorder" habe ich schon ziemlich viel von dem gefunden, was ich brauche. Also erstmal pauschal in mein Projekt integriert. Läuft im Prinzip auch so wie es soll.
    Nun sollen aber Teile der audiorecorder.ui auf die mainwindow.ui umziehen.

    Aber irgendwie blicke ich das nicht mit den Signalen/Slots.

    Hier ist die original Klasse vom audiorecorder

    QT_BEGIN_NAMESPACE
    namespace Ui { class AudioRecorder; }
    class QAudioRecorder;
    class QAudioProbe;
    class QAudioBuffer;
    QT_END_NAMESPACE
    
    class AudioLevel;
    
    class AudioRecorder : public QMainWindow
    {
    Q_OBJECT
    
    public:
    AudioRecorder();
    
    public slots:
    void processBuffer(const QAudioBuffer&);
    
    private slots:
    void setOutputLocation();
    void togglePause();
    void toggleRecord();
    
    void updateStatus(QMediaRecorder::Status);
    void onStateChanged(QMediaRecorder::State);
    void updateProgress(qint64 pos);
    void displayErrorMessage();
    
    private:
    void clearAudioLevels();
    
    Ui::AudioRecorder *ui = nullptr;
    
    QAudioRecorder *m_audioRecorder = nullptr;
    QAudioProbe *m_probe = nullptr;
    QList<AudioLevel*> m_audioLevels;
    bool m_outputLocationSet = false;
    
    };
    

    die audiorecorder.cpp habe ich ebenfalls noch unangetastet gelassen.

    In der mainwindow.cpp habe ich nun folgendes versucht:

    MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
    
    {
    ui->setupUi(this);
    
    connect(ui->constantQualityRadioButton, &QRadioButton::toggled, this, &MainWindow::setEnabled);
    connect(ui->constantBitrateRadioButton, &QRadioButton::toggled, this, &MainWindow::setEnabled);
    AudioRecorder *audioRecorder = new AudioRecorder;
    connect(ui->outputButton, &QPushButton::clicked, this, &audioRecorder->setOutputLocation());
    connect(ui->recordButton, &QPushButton::clicked, this, &audioRecorder->toggleRecord());
    connect(ui->pauseButton, &QPushButton::clicked, this, &audioRecorder->togglePause());
    
    
    }
    

    Funktioniert natürlich nicht wirklich. Nachdem ich jetzt über zwei Tage hinweg immer wieder mal daran gesessen habe,
    hoffe ich, Ihr könnt mir zeigen wie es richtig geht.

    VG
    Matze

    JonBJ Offline
    JonBJ Offline
    JonB
    wrote on last edited by JonB
    #2

    @MHage
    Kompiliert das eigentlich?

    connect(ui->constantQualityRadioButton, &QRadioButton::toggled, this, &MainWindow::setEnabled);
    

    Gut, korrekt!

    connect(ui->outputButton, &QPushButton::clicked, this, &audioRecorder->setOutputLocation());
    

    Schlecht, falsch! Das muesst ein Funktionsreferenz und nicht ein Funktionsaufruf sein, wie die früheren:

    connect(ui->outputButton, &QPushButton::clicked, audioRecorder, &AudioRecorder::setOutputLocation);
    
    1 Reply Last reply
    1
    • Axel SpoerlA Offline
      Axel SpoerlA Offline
      Axel Spoerl
      Moderators
      wrote on last edited by
      #3

      Zusätzlich zu dem, was @JonB geschrieben hat:
      Mir ist die Class Inheritance nicht ganz klar: AudioRecorder inherits from QMainWindow. Dann gibt es MainWindow, das ebenfalls von QMainWindow inherited. Im Konstruktor von MainWindow wird ein neuer AudioRecorder instatiiert, aber im connect Statement mit this referenziert. Die angeschlossenen Slots setOutputLocation(); togglePause(); toggleRecord(); sind private Slots von AudioRecorder. Sie können von einer anderen Klasse aus nicht genutzt werden.
      Ausgehend davon, dass alles andere irgendwie seine Richtigkeit hat, müssten die drei Slots public sein:

      public slots:
      void setOutputLocation();
      void togglePause();
      void toggleRecord();
      

      Die drei connect Statements müssten dann lauten:

      Q_ASSERT(connect(ui->outputButton, &QPushButton::clicked, audioRecorder, &audioRecorder::setOutputLocation));
      Q_ASSERT(connect(ui->recordButton, &QPushButton::clicked, audioRecorder, &audioRecorder::toggleRecord));
      Q_ASSERT(connect(ui->pauseButton, &QPushButton::clicked, audioRecorder, &audioRecorder::togglePause));
      

      Das Q_ASSERT bewirkt einen Crash, wenn das Connect Statement schief geht.

      Software Engineer
      The Qt Company, Oslo

      JonBJ 1 Reply Last reply
      0
      • Axel SpoerlA Axel Spoerl

        Zusätzlich zu dem, was @JonB geschrieben hat:
        Mir ist die Class Inheritance nicht ganz klar: AudioRecorder inherits from QMainWindow. Dann gibt es MainWindow, das ebenfalls von QMainWindow inherited. Im Konstruktor von MainWindow wird ein neuer AudioRecorder instatiiert, aber im connect Statement mit this referenziert. Die angeschlossenen Slots setOutputLocation(); togglePause(); toggleRecord(); sind private Slots von AudioRecorder. Sie können von einer anderen Klasse aus nicht genutzt werden.
        Ausgehend davon, dass alles andere irgendwie seine Richtigkeit hat, müssten die drei Slots public sein:

        public slots:
        void setOutputLocation();
        void togglePause();
        void toggleRecord();
        

        Die drei connect Statements müssten dann lauten:

        Q_ASSERT(connect(ui->outputButton, &QPushButton::clicked, audioRecorder, &audioRecorder::setOutputLocation));
        Q_ASSERT(connect(ui->recordButton, &QPushButton::clicked, audioRecorder, &audioRecorder::toggleRecord));
        Q_ASSERT(connect(ui->pauseButton, &QPushButton::clicked, audioRecorder, &audioRecorder::togglePause));
        

        Das Q_ASSERT bewirkt einen Crash, wenn das Connect Statement schief geht.

        JonBJ Offline
        JonBJ Offline
        JonB
        wrote on last edited by
        #4

        @Axel-Spoerl said in Zugriff auf Methoden anderer Klassen:

        Q_ASSERT(connect(ui->outputButton, &QPushButton::clicked, audioRecorder, &audioRecorder::setOutputLocation));

        Die Klasse ist AudioRecorder buchstabiert, also &audioRecorder::setOutputLocation -> &AudioRecorder::setOutputLocation.

        Entschúldigung, aber ich wuerde nie Q_ASSERT(connect(...)) schreiben. Wenn man mit QT_NO_DEBUG kompiliert, das wird: #define Q_ASSERT(cond) qt_noop(). Also die connect() wird nicht ausgeführt.

        Axel SpoerlA 1 Reply Last reply
        2
        • JonBJ JonB

          @Axel-Spoerl said in Zugriff auf Methoden anderer Klassen:

          Q_ASSERT(connect(ui->outputButton, &QPushButton::clicked, audioRecorder, &audioRecorder::setOutputLocation));

          Die Klasse ist AudioRecorder buchstabiert, also &audioRecorder::setOutputLocation -> &AudioRecorder::setOutputLocation.

          Entschúldigung, aber ich wuerde nie Q_ASSERT(connect(...)) schreiben. Wenn man mit QT_NO_DEBUG kompiliert, das wird: #define Q_ASSERT(cond) qt_noop(). Also die connect() wird nicht ausgeführt.

          Axel SpoerlA Offline
          Axel SpoerlA Offline
          Axel Spoerl
          Moderators
          wrote on last edited by
          #5

          @JonB said in Zugriff auf Methoden anderer Klassen:

          Also die connect() wird nicht ausgeführt.

          Das stimmt.
          Besser:

          const bool success = connect(...);
          Q_ASSERT(success).
          

          Software Engineer
          The Qt Company, Oslo

          JonBJ 1 Reply Last reply
          1
          • M Offline
            M Offline
            MHage
            wrote on last edited by
            #6

            Erstmal vielen Dank für die Unterstützung.
            Damit bin ich jetzt schon einen großen Schritt weitergekommen.

            Ein, zwei Fragen habe ich aber dennoch

            AudioRecorder *audioRecorder = new AudioRecorder;
            

            Wann und wo müsste ich am Besten audioRecorder wieder löschen? Nach meinem Verständnis wäre es hier wohl richtig:

            MainWindow::~MainWindow() {delete ui;}
            

            nur ist audioRecorder ja dort gar nicht bekannt.

            Anderes Thema, ich habe nun über connect den Weg von Form "MainWindow" nach AudioRecorder.
            Nun müsste ich die Objekte auf Form "MainWindow" mit Aktualwerten vom AudioRecorder beschreiben.

            Hier ein ein etwas zusammengestückeltes Fragment aus der AudioRecorder.cpp

            AudioRecorder::AudioRecorder(QWidget *parent) :
                QDialog(parent),
                ui(new Ui::AudioRecorder)
            {
                ui->setupUi(this);
            
                m_audioRecorder = new QAudioRecorder(this);
                m_probe = new QAudioProbe(this);
                connect(m_probe, &QAudioProbe::audioBufferProbed, this, &AudioRecorder::processBuffer);
                m_probe->setSource(m_audioRecorder);
            
            *************
            
            void AudioRecorder::updateProgress(qint64 duration)
            {
                if (m_audioRecorder->error() != QMediaRecorder::NoError || duration < 2000)
                    return;
                
                ui->statusbar->showMessage(tr("Recorded %1 sec").arg(duration / 1000));
            }
            
            
            

            so wurde es ursprünglich geschrieben. Gibt es eine Möglichkeit "ui->" mit der MainForm auszutauschen?
            Oder brauche ich jetzt public Slots in der Class MainWindow? Wie sollten die aussehen?

            Schon mal vielen Dank für eure Mühe...

            1 Reply Last reply
            0
            • Axel SpoerlA Offline
              Axel SpoerlA Offline
              Axel Spoerl
              Moderators
              wrote on last edited by Axel Spoerl
              #7

              ad Frage 1)
              Der AudioRecorder heißt einmal audioRecorder und es sieht so aus, als wird er im Scope einer Methode instatiiert. Dort muss er wieder gelöscht werden, ansonsten leaked er. Das ist der falsche Weg, da die angeschlossenen Signale offenbar den Scope der Methode (Konstruktor?) überleben sollen.

              Ein anderes mal heißt er m_audioRecorder. Das scheint der richtige Weg zu sein: Eine member variable, im Header deklariert und ergo im Destruktor bekannt. Damit kann er Destruktor der Klasse gelöscht werden in der die member variable deklariert wurde. Da nur Code-Fragmente gepostet sind, ist das wohl der Destruktor von MainWindow. Dort gehört dann delete m_audioRecorder;hinein.

              Eine stabile und einfache Variante, die ich gerne verwende, ist std::unique_ptr. Damit braucht man sich um's Löschen nicht mehr zu kümmern.

              Deklaration im header:
              std::unique_ptr<AudioRecorder> m_audioRecorder;

              Implementierung:
              m_audioRecorder.reset(new AudioRecorder);

              ad Frage 2)
              Verstehe ich nicht ganz. ui-> ist nur in der Ui-Klasse bekannt. Die Kommunikation sollte über Signals/Slots erfolgen.
              Wie die aussehen sollen - das sprengt diesen Rahmen etwas.

              Software Engineer
              The Qt Company, Oslo

              1 Reply Last reply
              2
              • Axel SpoerlA Axel Spoerl

                @JonB said in Zugriff auf Methoden anderer Klassen:

                Also die connect() wird nicht ausgeführt.

                Das stimmt.
                Besser:

                const bool success = connect(...);
                Q_ASSERT(success).
                
                JonBJ Offline
                JonBJ Offline
                JonB
                wrote on last edited by
                #8

                @Axel-Spoerl said in Zugriff auf Methoden anderer Klassen:

                const bool success = connect(...);
                Q_ASSERT(success).

                [Auf Englisch, entschuldigung :) ]
                This bothered me, having to write 2 lines for each such statement. What we want is something which always evaluates/executes its argument (unlike Q_ASSERT() which may not), but only bothers to test the result and fail in debug mode (like Q_ASSERT()). Turns out

                Q_ASSUME(connect(...));
                

                does just this :)

                1 Reply Last reply
                1
                • Axel SpoerlA Offline
                  Axel SpoerlA Offline
                  Axel Spoerl
                  Moderators
                  wrote on last edited by
                  #9

                  Nice find!

                  Software Engineer
                  The Qt Company, Oslo

                  1 Reply Last reply
                  0
                  • M Offline
                    M Offline
                    MHage
                    wrote on last edited by
                    #10

                    Hallo,

                    ist nun schon eine Weile her, kämpfe aber noch immer mit meinem Problem.
                    Daher möchte ich das jetzt nochmal aufgreifen.

                    Ich möchte auf Objekte auf dem Form MainWindow zugreifen.
                    Habe jetzt folgendes deklariert:

                    class MainWindow : public QMainWindow
                    {
                        Q_OBJECT
                    
                    public:
                        MainWindow(QWidget *parent = nullptr);
                            ~MainWindow();
                    
                    public slots:
                        QStatusBar statusbar();
                        QPushButton recordButton();
                        QPushButton pauseButton();
                        QComboBox *bitrateBox();
                        QVBoxLayout levelsLayout();
                        QSlider qualitySlider();
                        QRadioButton constantQualityRadioButton();
                    
                    
                    private slots:
                        void on_pushButton_clicked();
                        void on_actionAufnahmeparameter_triggered();
                    
                    
                    
                    private:
                        Ui::MainWindow *ui;
                        AudioRecorder *m_audioRecorder = nullptr;
                        void clearAudioLevels();
                    
                    };
                    #endif // MAINWINDOW_H
                    

                    Auf die public_slots möchte ich von der audiorecorder.cpp zugreifen.

                    Dazu habe ich dort folgendes deklariert:

                    audiorecorder.h (auszugsweise)

                    private:
                    MainWindow *m_mainWindow = nullptr;
                    

                    audiorecorder.cpp (auszugsweise)

                    AudioRecorder::AudioRecorder(QWidget *parent) :
                        QDialog(parent),
                        ui(new Ui::AudioRecorder)
                    {
                        ui->setupUi(this);
                    
                        m_audioRecorder = new QAudioRecorder(this);
                        m_probe = new QAudioProbe(this);
                        connect(m_probe, &QAudioProbe::audioBufferProbed, this, &AudioRecorder::processBuffer);
                        m_probe->setSource(m_audioRecorder);
                    
                        m_mainWindow = new QMainWindow(MainWindow);
                    }
                    
                    AudioRecorder::~AudioRecorder()
                    {
                        delete ui;
                        delete m_mainWindow;
                    }
                    
                    void AudioRecorder::onStateChanged(QMediaRecorder::State state)
                    {
                        switch (state) {
                        case QMediaRecorder::RecordingState:
                            //ui->recordButton->setText(tr("Stop"));
                            //ui->pauseButton->setText(tr("Pause"));
                            m_mainWindow->recordButton().setText(tr("Stop"));
                            m_mainWindow->pauseButton().setText(tr("Pause"));
                            break;
                        case QMediaRecorder::PausedState:
                            //ui->recordButton->setText(tr("Stop"));
                            //ui->pauseButton->setText(tr("Resume"));
                            m_mainWindow->recordButton().setText(tr("Stop"));
                            m_mainWindow->pauseButton().setText(tr("Resume"));
                            break;
                        case QMediaRecorder::StoppedState:
                            //ui->recordButton->setText(tr("Record"));
                            //ui->pauseButton->setText(tr("Pause"));
                            m_mainWindow->recordButton().setText(tr("Stop"));
                            m_mainWindow->pauseButton().setText(tr("Pause"));
                            break;
                        }
                    
                        //ui->pauseButton->setEnabled(m_audioRecorder->state() != QMediaRecorder::StoppedState);
                        m_mainWindow->pauseButton().setEnabled(m_audioRecorder->state() != QMediaRecorder::StoppedState);
                    }
                    

                    Ich kann nun, wie man in der Funktion "onStateChanged" beispielhaft sehen kann, auf die Objekte von MainWindow zugreifen.

                    Es wird auch nichts als Fehler oder Problem markiert. Sieht erstmal schön aus.
                    Lässt sich nur leider nicht kompilieren. Bekomme folgende Fehlermeldung:

                    audiorecorder.h:57: Fehler: ‘MainWindow’ does not name a type; did you mean ‘QMainWindow’?
                    In file included from mainwindow.h:17,
                                     from mainwindow.cpp:1:
                    audiorecorder.h:57:5: error: ‘MainWindow’ does not name a type; did you mean ‘QMainWindow’?
                       57 |     MainWindow *m_mainWindow = nullptr;
                          |     ^~~~~~~~~~
                          |     QMainWindow
                    
                    
                    mainwindow.cpp:11: Fehler: expected primary-expression before ‘)’ token
                    mainwindow.cpp:11:55: error: expected primary-expression before ‘)’ token
                       11 |     m_audioRecorder = new QAudioRecorder(AudioRecorder);
                          |                                                       ^
                    
                    mainwindow.h:49: Fehler: ‘AudioRecorder’ does not name a type; did you mean ‘QAudioRecorder’?
                    In file included from audiorecorder.h:13,
                                     from audiorecorder.cpp:1:
                    mainwindow.h:49:5: error: ‘AudioRecorder’ does not name a type; did you mean ‘QAudioRecorder’?
                       49 |     AudioRecorder *m_audioRecorder = nullptr;
                          |     ^~~~~~~~~~~~~
                          |     QAudioRecorder
                    
                    
                    
                    audiorecorder.cpp:25: Fehler: expected primary-expression before ‘)’ token
                    audiorecorder.cpp:25:46: error: expected primary-expression before ‘)’ token
                       25 |     m_mainWindow = new QMainWindow(MainWindow);
                          |                                              ^
                    
                    

                    Ich habe zwar Geduld, aber nach zwei Wochen ohne Erfolg hoffe ich auf ein wenig Hilfe von euch...

                    VG
                    Matze

                    1 Reply Last reply
                    0
                    • Axel SpoerlA Offline
                      Axel SpoerlA Offline
                      Axel Spoerl
                      Moderators
                      wrote on last edited by Axel Spoerl
                      #11

                      Bitte poste alle .cpp und .h files vollständig.
                      Das Problem liest sich wie rekursive #include statements. Das bekommen wir in den Griff.
                      LG
                      Axel

                      Software Engineer
                      The Qt Company, Oslo

                      1 Reply Last reply
                      0
                      • J.HilkJ Offline
                        J.HilkJ Offline
                        J.Hilk
                        Moderators
                        wrote on last edited by
                        #12

                        @MHage said in Zugriff auf Methoden anderer Klassen:

                        in MainWindow.h hast du

                        AudioRecorder *m_audioRecorder = nullptr;

                        in AudioRecorder hast du

                        m_mainWindow = new QMainWindow(MainWindow);

                        hier stimmt was hinten und vorne nicht und wenn es kompilieren würde, fürchte ich gehst du davon aus, dass du nur 1 MainWindow Instance hast, anstatt 2.

                        Es sieht für mich so aus, als ob dein AudioRecorder instance in MainWindow instanziert wird. So weit so gut, dann brauchst du entweder Setters in AudioRecorder die du von deiner MainWindow instance aus fütterst oder du kommunizierst via Signals und Slots zwischen den beiden Instanzen. Was auch prinzipiell der bessere Weg ist. Deutlich weniger Spaghetti dann


                        Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                        Q: What's that?
                        A: It's blue light.
                        Q: What does it do?
                        A: It turns blue.

                        1 Reply Last reply
                        1
                        • M Offline
                          M Offline
                          MHage
                          wrote on last edited by MHage
                          #13

                          Das lässt hoffen. Ich habe nämlich komplett den Faden verloren...

                          mainwindow.h

                          #ifndef MAINWINDOW_H
                          #define MAINWINDOW_H
                          
                          #include <QMainWindow>
                          #include <QUrl>
                          #include <QDir>
                          #include <QFileDialog>
                          #include <QStandardPaths>
                          #include <QObject>
                          #include <QMultimedia>
                          #include <QAudioRecorder>
                          #include <QMediaRecorder>
                          #include <QSlider>
                          #include <QRadioButton>
                          
                          #include "audiodevicesbase.h"
                          #include "audiorecorder.h"
                          
                          QT_BEGIN_NAMESPACE
                          namespace Ui { class MainWindow; }
                          QT_END_NAMESPACE
                          
                          class MainWindow : public QMainWindow
                          {
                              Q_OBJECT
                          
                          public:
                              MainWindow(QWidget *parent = nullptr);
                                  ~MainWindow();
                          
                          public slots:
                              QStatusBar statusbar();
                              QPushButton recordButton();
                              QPushButton pauseButton();
                              QComboBox *bitrateBox();
                              QVBoxLayout levelsLayout();
                              QSlider qualitySlider();
                              QRadioButton constantQualityRadioButton();
                          
                          
                          private slots:
                              void on_pushButton_clicked();
                              void on_actionAufnahmeparameter_triggered();
                          
                          
                          
                          private:
                              Ui::MainWindow *ui;
                              AudioRecorder *m_audioRecorder = nullptr;
                              void clearAudioLevels();
                          
                          };
                          #endif // MAINWINDOW_H
                          
                          

                          mainwoindow.cpp

                          #include "mainwindow.h"
                          #include "ui_mainwindow.h"
                          
                          
                          
                          MainWindow::MainWindow(QWidget *parent)
                              : QMainWindow(parent)
                              , ui(new Ui::MainWindow)
                          {
                              ui->setupUi(this);
                              m_audioRecorder = new QAudioRecorder(AudioRecorder);
                          
                              //connect(ui->constantQualityRadioButton, &QRadioButton::toggled, this, &MainWindow::setEnabled);
                              //connect(ui->constantBitrateRadioButton, &QRadioButton::toggled, this, &MainWindow::setEnabled);
                          
                              //Q_ASSUME(connect(ui->actionSpeichern, &QMenuBar::triggered, audioRecorder, &AudioRecorder::setOutputLocation));
                              Q_ASSUME(connect(ui->outputButton, &QPushButton::clicked, m_audioRecorder, &AudioRecorder::setOutputLocation));
                              Q_ASSUME(connect(ui->recordButton, &QPushButton::clicked, m_audioRecorder, &AudioRecorder::toggleRecord));
                              Q_ASSUME(connect(ui->pauseButton, &QPushButton::clicked, m_audioRecorder, &AudioRecorder::togglePause));
                          
                              //quality
                              ui->qualitySlider->setRange(0, int(QMultimedia::VeryHighQuality));
                              ui->qualitySlider->setValue(int(QMultimedia::NormalQuality));
                          
                              //bitrates:
                              ui->bitrateBox->addItem(tr("Default"), QVariant(0));
                              ui->bitrateBox->addItem(QStringLiteral("32000"), QVariant(32000));
                              ui->bitrateBox->addItem(QStringLiteral("64000"), QVariant(64000));
                              ui->bitrateBox->addItem(QStringLiteral("96000"), QVariant(96000));
                              ui->bitrateBox->addItem(QStringLiteral("128000"), QVariant(128000));
                          }
                          
                          
                          MainWindow::~MainWindow()
                          {
                              delete ui;
                              delete m_audioRecorder;
                          }
                          

                          audiorecorder.h

                          #ifndef AUDIORECORDER_H
                          #define AUDIORECORDER_H
                          
                          #include <QUrl>
                          #include <QAudioProbe>
                          #include <QAudioRecorder>
                          #include <QMediaRecorder>
                          #include <QDir>
                          #include <QFileDialog>
                          #include <QStandardPaths>
                          #include <QDialog>
                          
                          #include "mainwindow.h"
                          
                          
                          QT_BEGIN_NAMESPACE
                          namespace Ui { class AudioRecorder; }
                          class QAudioRecorder;
                          class QAudioProbe;
                          class QAudioBuffer;
                          QT_END_NAMESPACE
                          
                          class AudioLevel;
                          
                          
                          class AudioRecorder : public QDialog
                          {
                              Q_OBJECT
                          
                          public:
                              explicit AudioRecorder(QWidget *parent = nullptr);
                              ~AudioRecorder();
                          
                          public slots:
                              void processBuffer(const QAudioBuffer&);
                          
                              void setOutputLocation();
                              void togglePause();
                              void toggleRecord();
                          
                              void updateStatus(QMediaRecorder::Status);
                              void onStateChanged(QMediaRecorder::State);
                              void updateProgress(qint64 pos);
                              void displayErrorMessage();
                          
                          private slots:
                          
                          
                          private:
                          
                              QAudioRecorder *m_audioRecorder = nullptr;
                              bool m_outputLocationSet = false;
                              QAudioProbe *m_probe = nullptr;
                              QList<AudioLevel*> m_audioLevels;
                          
                              void clearAudioLevels();
                              MainWindow *m_mainWindow = nullptr;
                          
                              Ui::AudioRecorder *ui = nullptr;
                          };
                          
                          #endif // AUDIORECORDER_H
                          
                          

                          audiorecorder.cpp

                          #include "audiorecorder.h"
                          #include "audiolevel.h"
                          #include "ui_audiorecorder.h"
                          
                          #include "mainwindow.h"
                          #include "ui_mainwindow.h"
                          
                          static qreal getPeakValue(const QAudioFormat &format);
                          static QVector<qreal> getBufferLevels(const QAudioBuffer &buffer);
                          
                          template <class T>
                          static QVector<qreal> getBufferLevels(const T *buffer, int frames, int channels);
                          
                          AudioRecorder::AudioRecorder(QWidget *parent) :
                              QDialog(parent),
                              ui(new Ui::AudioRecorder)
                          {
                              ui->setupUi(this);
                          
                              m_audioRecorder = new QAudioRecorder(this);
                              m_probe = new QAudioProbe(this);
                              connect(m_probe, &QAudioProbe::audioBufferProbed, this, &AudioRecorder::processBuffer);
                              m_probe->setSource(m_audioRecorder);
                          
                              m_mainWindow = new QMainWindow(MainWindow);
                          
                              //audio devices
                              ui->audioDeviceBox->addItem(tr("Default"), QVariant(QString()));
                              for (auto &device: m_audioRecorder->audioInputs()) {
                                  ui->audioDeviceBox->addItem(device, QVariant(device));
                              }
                          
                              //audio codecs
                              ui->audioCodecBox->addItem(tr("Default"), QVariant(QString()));
                              for (auto &codecName: m_audioRecorder->supportedAudioCodecs()) {
                                  ui->audioCodecBox->addItem(codecName, QVariant(codecName));
                              }
                          
                              //containers
                              ui->containerBox->addItem(tr("Default"), QVariant(QString()));
                              for (auto &containerName: m_audioRecorder->supportedContainers()) {
                                  ui->containerBox->addItem(containerName, QVariant(containerName));
                              }
                          
                              //sample rate
                              ui->sampleRateBox->addItem(tr("Default"), QVariant(0));
                              for (int sampleRate: m_audioRecorder->supportedAudioSampleRates()) {
                                  ui->sampleRateBox->addItem(QString::number(sampleRate), QVariant(
                                          sampleRate));
                              }
                          
                              //channels
                              ui->channelsBox->addItem(tr("Default"), QVariant(-1));
                              ui->channelsBox->addItem(QStringLiteral("1"), QVariant(1));
                              ui->channelsBox->addItem(QStringLiteral("2"), QVariant(2));
                              ui->channelsBox->addItem(QStringLiteral("4"), QVariant(4));
                          
                              /*
                              //quality
                              ui->qualitySlider->setRange(0, int(QMultimedia::VeryHighQuality));
                              ui->qualitySlider->setValue(int(QMultimedia::NormalQuality));
                          
                              //bitrates:
                              ui->bitrateBox->addItem(tr("Default"), QVariant(0));
                              ui->bitrateBox->addItem(QStringLiteral("32000"), QVariant(32000));
                              ui->bitrateBox->addItem(QStringLiteral("64000"), QVariant(64000));
                              ui->bitrateBox->addItem(QStringLiteral("96000"), QVariant(96000));
                              ui->bitrateBox->addItem(QStringLiteral("128000"), QVariant(128000));
                              */
                          
                              connect(m_audioRecorder, &QAudioRecorder::durationChanged, this, &AudioRecorder::updateProgress);
                              connect(m_audioRecorder, &QAudioRecorder::durationChanged, this, &AudioRecorder::updateProgress);
                              connect(m_audioRecorder, &QAudioRecorder::statusChanged, this, &AudioRecorder::updateStatus);
                              connect(m_audioRecorder, &QAudioRecorder::stateChanged, this, &AudioRecorder::onStateChanged);
                              connect(m_audioRecorder, QOverload<QMediaRecorder::Error>::of(&QAudioRecorder::error), this, &AudioRecorder::displayErrorMessage);
                          }
                          
                          AudioRecorder::~AudioRecorder()
                          {
                              delete ui;
                              delete m_mainWindow;
                          }
                          
                          
                          void AudioRecorder::updateProgress(qint64 duration)
                          {
                              if (m_audioRecorder->error() != QMediaRecorder::NoError || duration < 2000)
                                  return;
                          
                              //ui->statusbar->showMessage(tr("Recorded %1 sec").arg(duration / 1000));
                              m_mainWindow->statusbar().showMessage(tr("Recorded %1 sec").arg(duration / 1000));
                          }
                          
                          void AudioRecorder::updateStatus(QMediaRecorder::Status status)
                          {
                              QString statusMessage;
                          
                              switch (status) {
                              case QMediaRecorder::RecordingStatus:
                                  statusMessage = tr("Recording to %1").arg(m_audioRecorder->actualLocation().toString());
                                  break;
                              case QMediaRecorder::PausedStatus:
                                  clearAudioLevels();
                                  statusMessage = tr("Paused");
                                  break;
                              case QMediaRecorder::UnloadedStatus:
                              case QMediaRecorder::LoadedStatus:
                                  clearAudioLevels();
                                  statusMessage = tr("Stopped");
                              default:
                                  break;
                              }
                          
                              if (m_audioRecorder->error() == QMediaRecorder::NoError)
                                  //ui->statusbar->showMessage(statusMessage);
                                  m_mainWindow->statusbar().showMessage(statusMessage);
                          }
                          
                          void AudioRecorder::onStateChanged(QMediaRecorder::State state)
                          {
                              switch (state) {
                              case QMediaRecorder::RecordingState:
                                  //ui->recordButton->setText(tr("Stop"));
                                  //ui->pauseButton->setText(tr("Pause"));
                                  m_mainWindow->recordButton().setText(tr("Stop"));
                                  m_mainWindow->pauseButton().setText(tr("Pause"));
                                  break;
                              case QMediaRecorder::PausedState:
                                  //ui->recordButton->setText(tr("Stop"));
                                  //ui->pauseButton->setText(tr("Resume"));
                                  m_mainWindow->recordButton().setText(tr("Stop"));
                                  m_mainWindow->pauseButton().setText(tr("Resume"));
                                  break;
                              case QMediaRecorder::StoppedState:
                                  //ui->recordButton->setText(tr("Record"));
                                  //ui->pauseButton->setText(tr("Pause"));
                                  m_mainWindow->recordButton().setText(tr("Stop"));
                                  m_mainWindow->pauseButton().setText(tr("Pause"));
                                  break;
                              }
                          
                              //ui->pauseButton->setEnabled(m_audioRecorder->state() != QMediaRecorder::StoppedState);
                              m_mainWindow->pauseButton().setEnabled(m_audioRecorder->state() != QMediaRecorder::StoppedState);
                          }
                          
                          static QVariant boxValue(const QComboBox *box)
                          {
                              int idx = box->currentIndex();
                              if (idx == -1)
                                  return QVariant();
                          
                              return box->itemData(idx);
                          }
                          
                          void AudioRecorder::toggleRecord()
                          {
                              if (m_audioRecorder->state() == QMediaRecorder::StoppedState) {
                                  m_audioRecorder->setAudioInput(boxValue(ui->audioDeviceBox).toString());
                          
                                  QAudioEncoderSettings settings;
                                  settings.setCodec(boxValue(ui->audioCodecBox).toString());
                                  settings.setSampleRate(boxValue(ui->sampleRateBox).toInt());
                                  //settings.setBitRate(boxValue(ui->bitrateBox).toInt());
                                  settings.setBitRate(boxValue(m_mainWindow->bitrateBox()).toInt());
                          
                                  settings.setChannelCount(boxValue(ui->channelsBox).toInt());
                                  //settings.setQuality(QMultimedia::EncodingQuality(ui->qualitySlider->value()));
                                  settings.setQuality(QMultimedia::EncodingQuality(m_mainWindow->qualitySlider().value()));
                                  //settings.setEncodingMode(ui->constantQualityRadioButton->isChecked() ?
                                  //                         QMultimedia::ConstantQualityEncoding :
                                  //                         QMultimedia::ConstantBitRateEncoding);
                                  settings.setEncodingMode(m_mainWindow->constantQualityRadioButton().isChecked() ?
                                                           QMultimedia::ConstantQualityEncoding :
                                                           QMultimedia::ConstantBitRateEncoding);
                          
                                  QString container = boxValue(ui->containerBox).toString();
                          
                                  m_audioRecorder->setEncodingSettings(settings, QVideoEncoderSettings(), container);
                                  m_audioRecorder->record();
                              }
                              else {
                                  m_audioRecorder->stop();
                              }
                          }
                          
                          void AudioRecorder::togglePause()
                          {
                              if (m_audioRecorder->state() != QMediaRecorder::PausedState)
                                  m_audioRecorder->pause();
                              else
                                  m_audioRecorder->record();
                          }
                          
                          void AudioRecorder::setOutputLocation()
                          {
                          #ifdef Q_OS_WINRT
                              // UWP does not allow to store outside the sandbox
                              const QString cacheDir = QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
                              if (!QDir().mkpath(cacheDir)) {
                                  qWarning() << "Failed to create cache directory";
                                  return;
                              }
                              QString fileName = cacheDir + QLatin1String("/output.wav");
                          #else
                              QString fileName = QFileDialog::getSaveFileName();
                          #endif
                              m_audioRecorder->setOutputLocation(QUrl::fromLocalFile(fileName));
                              m_outputLocationSet = true;
                          }
                          
                          
                          void AudioRecorder::displayErrorMessage()
                          {
                              //ui->statusbar->showMessage(m_audioRecorder->errorString());
                              m_mainWindow->statusbar().showMessage(m_audioRecorder->errorString());
                          }
                          
                          void AudioRecorder::clearAudioLevels()
                          {
                              for (int i = 0; i < m_audioLevels.size(); ++i)
                                  m_audioLevels.at(i)->setLevel(0);
                          }
                          
                          // This function returns the maximum possible sample value for a given audio format
                          qreal getPeakValue(const QAudioFormat& format)
                          {
                              // Note: Only the most common sample formats are supported
                              if (!format.isValid())
                                  return qreal(0);
                          
                              if (format.codec() != "audio/pcm")
                                  return qreal(0);
                          
                              switch (format.sampleType()) {
                              case QAudioFormat::Unknown:
                                  break;
                              case QAudioFormat::Float:
                                  if (format.sampleSize() != 32) // other sample formats are not supported
                                      return qreal(0);
                                  return qreal(1.00003);
                              case QAudioFormat::SignedInt:
                                  if (format.sampleSize() == 32)
                                      return qreal(INT_MAX);
                                  if (format.sampleSize() == 16)
                                      return qreal(SHRT_MAX);
                                  if (format.sampleSize() == 8)
                                      return qreal(CHAR_MAX);
                                  break;
                              case QAudioFormat::UnSignedInt:
                                  if (format.sampleSize() == 32)
                                      return qreal(UINT_MAX);
                                  if (format.sampleSize() == 16)
                                      return qreal(USHRT_MAX);
                                  if (format.sampleSize() == 8)
                                      return qreal(UCHAR_MAX);
                                  break;
                              }
                          
                              return qreal(0);
                          }
                          
                          // returns the audio level for each channel
                          QVector<qreal> getBufferLevels(const QAudioBuffer& buffer)
                          {
                              QVector<qreal> values;
                          
                              if (!buffer.format().isValid() || buffer.format().byteOrder() != QAudioFormat::LittleEndian)
                                  return values;
                          
                              if (buffer.format().codec() != "audio/pcm")
                                  return values;
                          
                              int channelCount = buffer.format().channelCount();
                              values.fill(0, channelCount);
                              qreal peak_value = getPeakValue(buffer.format());
                              if (qFuzzyCompare(peak_value, qreal(0)))
                                  return values;
                          
                              switch (buffer.format().sampleType()) {
                              case QAudioFormat::Unknown:
                              case QAudioFormat::UnSignedInt:
                                  if (buffer.format().sampleSize() == 32)
                                      values = getBufferLevels(buffer.constData<quint32>(), buffer.frameCount(), channelCount);
                                  if (buffer.format().sampleSize() == 16)
                                      values = getBufferLevels(buffer.constData<quint16>(), buffer.frameCount(), channelCount);
                                  if (buffer.format().sampleSize() == 8)
                                      values = getBufferLevels(buffer.constData<quint8>(), buffer.frameCount(), channelCount);
                                  for (int i = 0; i < values.size(); ++i)
                                      values[i] = qAbs(values.at(i) - peak_value / 2) / (peak_value / 2);
                                  break;
                              case QAudioFormat::Float:
                                  if (buffer.format().sampleSize() == 32) {
                                      values = getBufferLevels(buffer.constData<float>(), buffer.frameCount(), channelCount);
                                      for (int i = 0; i < values.size(); ++i)
                                          values[i] /= peak_value;
                                  }
                                  break;
                              case QAudioFormat::SignedInt:
                                  if (buffer.format().sampleSize() == 32)
                                      values = getBufferLevels(buffer.constData<qint32>(), buffer.frameCount(), channelCount);
                                  if (buffer.format().sampleSize() == 16)
                                      values = getBufferLevels(buffer.constData<qint16>(), buffer.frameCount(), channelCount);
                                  if (buffer.format().sampleSize() == 8)
                                      values = getBufferLevels(buffer.constData<qint8>(), buffer.frameCount(), channelCount);
                                  for (int i = 0; i < values.size(); ++i)
                                      values[i] /= peak_value;
                                  break;
                              }
                          
                              return values;
                          }
                          
                          template <class T>
                          QVector<qreal> getBufferLevels(const T *buffer, int frames, int channels)
                          {
                              QVector<qreal> max_values;
                              max_values.fill(0, channels);
                          
                              for (int i = 0; i < frames; ++i) {
                                  for (int j = 0; j < channels; ++j) {
                                      qreal value = qAbs(qreal(buffer[i * channels + j]));
                                      if (value > max_values.at(j))
                                          max_values.replace(j, value);
                                  }
                              }
                          
                              return max_values;
                          }
                          
                          void AudioRecorder::processBuffer(const QAudioBuffer& buffer)
                          {
                              if (m_audioLevels.count() != buffer.format().channelCount()) {
                                  qDeleteAll(m_audioLevels);
                                  m_audioLevels.clear();
                                  for (int i = 0; i < buffer.format().channelCount(); ++i) {
                                      AudioLevel *level = new AudioLevel(ui->centralwidget);
                                      m_audioLevels.append(level);
                                      //ui->levelsLayout->addWidget(level);
                                      m_mainWindow->levelsLayout().addWidget(level);
                                  }
                              }
                          
                              QVector<qreal> levels = getBufferLevels(buffer);
                              for (int i = 0; i < levels.count(); ++i)
                                  m_audioLevels.at(i)->setLevel(levels.at(i));
                          }
                          
                          
                          
                          JonBJ Pl45m4P 2 Replies Last reply
                          0
                          • Axel SpoerlA Offline
                            Axel SpoerlA Offline
                            Axel Spoerl
                            Moderators
                            wrote on last edited by Axel Spoerl
                            #14

                            Ein Problem ist, dass sich audiorecorder.hund mainwindow.h gegenseitig inkludieren.
                            Beim Kompilieren greift der include guard am Beginn der Dateien und der Rest steht in der Fehlermeldung.

                            Das Problem lässt sich lösen, indem in mainwindow.h das #include <audiorecorder.h> durch eine forward-declaration ersetzt wird: class AudioRecorder; Das entfernte include statement muss dann in mainwindow.cpp am Anfang eingefügt werden.

                            Da die Datei audiolevel.h nicht gepostet ist, lässt sich nicht beurteilen, ob sie weitere Probleme enthält und ggfs. den o.g. Lösungsweg zunichte macht.

                            Software Engineer
                            The Qt Company, Oslo

                            1 Reply Last reply
                            1
                            • M MHage

                              Das lässt hoffen. Ich habe nämlich komplett den Faden verloren...

                              mainwindow.h

                              #ifndef MAINWINDOW_H
                              #define MAINWINDOW_H
                              
                              #include <QMainWindow>
                              #include <QUrl>
                              #include <QDir>
                              #include <QFileDialog>
                              #include <QStandardPaths>
                              #include <QObject>
                              #include <QMultimedia>
                              #include <QAudioRecorder>
                              #include <QMediaRecorder>
                              #include <QSlider>
                              #include <QRadioButton>
                              
                              #include "audiodevicesbase.h"
                              #include "audiorecorder.h"
                              
                              QT_BEGIN_NAMESPACE
                              namespace Ui { class MainWindow; }
                              QT_END_NAMESPACE
                              
                              class MainWindow : public QMainWindow
                              {
                                  Q_OBJECT
                              
                              public:
                                  MainWindow(QWidget *parent = nullptr);
                                      ~MainWindow();
                              
                              public slots:
                                  QStatusBar statusbar();
                                  QPushButton recordButton();
                                  QPushButton pauseButton();
                                  QComboBox *bitrateBox();
                                  QVBoxLayout levelsLayout();
                                  QSlider qualitySlider();
                                  QRadioButton constantQualityRadioButton();
                              
                              
                              private slots:
                                  void on_pushButton_clicked();
                                  void on_actionAufnahmeparameter_triggered();
                              
                              
                              
                              private:
                                  Ui::MainWindow *ui;
                                  AudioRecorder *m_audioRecorder = nullptr;
                                  void clearAudioLevels();
                              
                              };
                              #endif // MAINWINDOW_H
                              
                              

                              mainwoindow.cpp

                              #include "mainwindow.h"
                              #include "ui_mainwindow.h"
                              
                              
                              
                              MainWindow::MainWindow(QWidget *parent)
                                  : QMainWindow(parent)
                                  , ui(new Ui::MainWindow)
                              {
                                  ui->setupUi(this);
                                  m_audioRecorder = new QAudioRecorder(AudioRecorder);
                              
                                  //connect(ui->constantQualityRadioButton, &QRadioButton::toggled, this, &MainWindow::setEnabled);
                                  //connect(ui->constantBitrateRadioButton, &QRadioButton::toggled, this, &MainWindow::setEnabled);
                              
                                  //Q_ASSUME(connect(ui->actionSpeichern, &QMenuBar::triggered, audioRecorder, &AudioRecorder::setOutputLocation));
                                  Q_ASSUME(connect(ui->outputButton, &QPushButton::clicked, m_audioRecorder, &AudioRecorder::setOutputLocation));
                                  Q_ASSUME(connect(ui->recordButton, &QPushButton::clicked, m_audioRecorder, &AudioRecorder::toggleRecord));
                                  Q_ASSUME(connect(ui->pauseButton, &QPushButton::clicked, m_audioRecorder, &AudioRecorder::togglePause));
                              
                                  //quality
                                  ui->qualitySlider->setRange(0, int(QMultimedia::VeryHighQuality));
                                  ui->qualitySlider->setValue(int(QMultimedia::NormalQuality));
                              
                                  //bitrates:
                                  ui->bitrateBox->addItem(tr("Default"), QVariant(0));
                                  ui->bitrateBox->addItem(QStringLiteral("32000"), QVariant(32000));
                                  ui->bitrateBox->addItem(QStringLiteral("64000"), QVariant(64000));
                                  ui->bitrateBox->addItem(QStringLiteral("96000"), QVariant(96000));
                                  ui->bitrateBox->addItem(QStringLiteral("128000"), QVariant(128000));
                              }
                              
                              
                              MainWindow::~MainWindow()
                              {
                                  delete ui;
                                  delete m_audioRecorder;
                              }
                              

                              audiorecorder.h

                              #ifndef AUDIORECORDER_H
                              #define AUDIORECORDER_H
                              
                              #include <QUrl>
                              #include <QAudioProbe>
                              #include <QAudioRecorder>
                              #include <QMediaRecorder>
                              #include <QDir>
                              #include <QFileDialog>
                              #include <QStandardPaths>
                              #include <QDialog>
                              
                              #include "mainwindow.h"
                              
                              
                              QT_BEGIN_NAMESPACE
                              namespace Ui { class AudioRecorder; }
                              class QAudioRecorder;
                              class QAudioProbe;
                              class QAudioBuffer;
                              QT_END_NAMESPACE
                              
                              class AudioLevel;
                              
                              
                              class AudioRecorder : public QDialog
                              {
                                  Q_OBJECT
                              
                              public:
                                  explicit AudioRecorder(QWidget *parent = nullptr);
                                  ~AudioRecorder();
                              
                              public slots:
                                  void processBuffer(const QAudioBuffer&);
                              
                                  void setOutputLocation();
                                  void togglePause();
                                  void toggleRecord();
                              
                                  void updateStatus(QMediaRecorder::Status);
                                  void onStateChanged(QMediaRecorder::State);
                                  void updateProgress(qint64 pos);
                                  void displayErrorMessage();
                              
                              private slots:
                              
                              
                              private:
                              
                                  QAudioRecorder *m_audioRecorder = nullptr;
                                  bool m_outputLocationSet = false;
                                  QAudioProbe *m_probe = nullptr;
                                  QList<AudioLevel*> m_audioLevels;
                              
                                  void clearAudioLevels();
                                  MainWindow *m_mainWindow = nullptr;
                              
                                  Ui::AudioRecorder *ui = nullptr;
                              };
                              
                              #endif // AUDIORECORDER_H
                              
                              

                              audiorecorder.cpp

                              #include "audiorecorder.h"
                              #include "audiolevel.h"
                              #include "ui_audiorecorder.h"
                              
                              #include "mainwindow.h"
                              #include "ui_mainwindow.h"
                              
                              static qreal getPeakValue(const QAudioFormat &format);
                              static QVector<qreal> getBufferLevels(const QAudioBuffer &buffer);
                              
                              template <class T>
                              static QVector<qreal> getBufferLevels(const T *buffer, int frames, int channels);
                              
                              AudioRecorder::AudioRecorder(QWidget *parent) :
                                  QDialog(parent),
                                  ui(new Ui::AudioRecorder)
                              {
                                  ui->setupUi(this);
                              
                                  m_audioRecorder = new QAudioRecorder(this);
                                  m_probe = new QAudioProbe(this);
                                  connect(m_probe, &QAudioProbe::audioBufferProbed, this, &AudioRecorder::processBuffer);
                                  m_probe->setSource(m_audioRecorder);
                              
                                  m_mainWindow = new QMainWindow(MainWindow);
                              
                                  //audio devices
                                  ui->audioDeviceBox->addItem(tr("Default"), QVariant(QString()));
                                  for (auto &device: m_audioRecorder->audioInputs()) {
                                      ui->audioDeviceBox->addItem(device, QVariant(device));
                                  }
                              
                                  //audio codecs
                                  ui->audioCodecBox->addItem(tr("Default"), QVariant(QString()));
                                  for (auto &codecName: m_audioRecorder->supportedAudioCodecs()) {
                                      ui->audioCodecBox->addItem(codecName, QVariant(codecName));
                                  }
                              
                                  //containers
                                  ui->containerBox->addItem(tr("Default"), QVariant(QString()));
                                  for (auto &containerName: m_audioRecorder->supportedContainers()) {
                                      ui->containerBox->addItem(containerName, QVariant(containerName));
                                  }
                              
                                  //sample rate
                                  ui->sampleRateBox->addItem(tr("Default"), QVariant(0));
                                  for (int sampleRate: m_audioRecorder->supportedAudioSampleRates()) {
                                      ui->sampleRateBox->addItem(QString::number(sampleRate), QVariant(
                                              sampleRate));
                                  }
                              
                                  //channels
                                  ui->channelsBox->addItem(tr("Default"), QVariant(-1));
                                  ui->channelsBox->addItem(QStringLiteral("1"), QVariant(1));
                                  ui->channelsBox->addItem(QStringLiteral("2"), QVariant(2));
                                  ui->channelsBox->addItem(QStringLiteral("4"), QVariant(4));
                              
                                  /*
                                  //quality
                                  ui->qualitySlider->setRange(0, int(QMultimedia::VeryHighQuality));
                                  ui->qualitySlider->setValue(int(QMultimedia::NormalQuality));
                              
                                  //bitrates:
                                  ui->bitrateBox->addItem(tr("Default"), QVariant(0));
                                  ui->bitrateBox->addItem(QStringLiteral("32000"), QVariant(32000));
                                  ui->bitrateBox->addItem(QStringLiteral("64000"), QVariant(64000));
                                  ui->bitrateBox->addItem(QStringLiteral("96000"), QVariant(96000));
                                  ui->bitrateBox->addItem(QStringLiteral("128000"), QVariant(128000));
                                  */
                              
                                  connect(m_audioRecorder, &QAudioRecorder::durationChanged, this, &AudioRecorder::updateProgress);
                                  connect(m_audioRecorder, &QAudioRecorder::durationChanged, this, &AudioRecorder::updateProgress);
                                  connect(m_audioRecorder, &QAudioRecorder::statusChanged, this, &AudioRecorder::updateStatus);
                                  connect(m_audioRecorder, &QAudioRecorder::stateChanged, this, &AudioRecorder::onStateChanged);
                                  connect(m_audioRecorder, QOverload<QMediaRecorder::Error>::of(&QAudioRecorder::error), this, &AudioRecorder::displayErrorMessage);
                              }
                              
                              AudioRecorder::~AudioRecorder()
                              {
                                  delete ui;
                                  delete m_mainWindow;
                              }
                              
                              
                              void AudioRecorder::updateProgress(qint64 duration)
                              {
                                  if (m_audioRecorder->error() != QMediaRecorder::NoError || duration < 2000)
                                      return;
                              
                                  //ui->statusbar->showMessage(tr("Recorded %1 sec").arg(duration / 1000));
                                  m_mainWindow->statusbar().showMessage(tr("Recorded %1 sec").arg(duration / 1000));
                              }
                              
                              void AudioRecorder::updateStatus(QMediaRecorder::Status status)
                              {
                                  QString statusMessage;
                              
                                  switch (status) {
                                  case QMediaRecorder::RecordingStatus:
                                      statusMessage = tr("Recording to %1").arg(m_audioRecorder->actualLocation().toString());
                                      break;
                                  case QMediaRecorder::PausedStatus:
                                      clearAudioLevels();
                                      statusMessage = tr("Paused");
                                      break;
                                  case QMediaRecorder::UnloadedStatus:
                                  case QMediaRecorder::LoadedStatus:
                                      clearAudioLevels();
                                      statusMessage = tr("Stopped");
                                  default:
                                      break;
                                  }
                              
                                  if (m_audioRecorder->error() == QMediaRecorder::NoError)
                                      //ui->statusbar->showMessage(statusMessage);
                                      m_mainWindow->statusbar().showMessage(statusMessage);
                              }
                              
                              void AudioRecorder::onStateChanged(QMediaRecorder::State state)
                              {
                                  switch (state) {
                                  case QMediaRecorder::RecordingState:
                                      //ui->recordButton->setText(tr("Stop"));
                                      //ui->pauseButton->setText(tr("Pause"));
                                      m_mainWindow->recordButton().setText(tr("Stop"));
                                      m_mainWindow->pauseButton().setText(tr("Pause"));
                                      break;
                                  case QMediaRecorder::PausedState:
                                      //ui->recordButton->setText(tr("Stop"));
                                      //ui->pauseButton->setText(tr("Resume"));
                                      m_mainWindow->recordButton().setText(tr("Stop"));
                                      m_mainWindow->pauseButton().setText(tr("Resume"));
                                      break;
                                  case QMediaRecorder::StoppedState:
                                      //ui->recordButton->setText(tr("Record"));
                                      //ui->pauseButton->setText(tr("Pause"));
                                      m_mainWindow->recordButton().setText(tr("Stop"));
                                      m_mainWindow->pauseButton().setText(tr("Pause"));
                                      break;
                                  }
                              
                                  //ui->pauseButton->setEnabled(m_audioRecorder->state() != QMediaRecorder::StoppedState);
                                  m_mainWindow->pauseButton().setEnabled(m_audioRecorder->state() != QMediaRecorder::StoppedState);
                              }
                              
                              static QVariant boxValue(const QComboBox *box)
                              {
                                  int idx = box->currentIndex();
                                  if (idx == -1)
                                      return QVariant();
                              
                                  return box->itemData(idx);
                              }
                              
                              void AudioRecorder::toggleRecord()
                              {
                                  if (m_audioRecorder->state() == QMediaRecorder::StoppedState) {
                                      m_audioRecorder->setAudioInput(boxValue(ui->audioDeviceBox).toString());
                              
                                      QAudioEncoderSettings settings;
                                      settings.setCodec(boxValue(ui->audioCodecBox).toString());
                                      settings.setSampleRate(boxValue(ui->sampleRateBox).toInt());
                                      //settings.setBitRate(boxValue(ui->bitrateBox).toInt());
                                      settings.setBitRate(boxValue(m_mainWindow->bitrateBox()).toInt());
                              
                                      settings.setChannelCount(boxValue(ui->channelsBox).toInt());
                                      //settings.setQuality(QMultimedia::EncodingQuality(ui->qualitySlider->value()));
                                      settings.setQuality(QMultimedia::EncodingQuality(m_mainWindow->qualitySlider().value()));
                                      //settings.setEncodingMode(ui->constantQualityRadioButton->isChecked() ?
                                      //                         QMultimedia::ConstantQualityEncoding :
                                      //                         QMultimedia::ConstantBitRateEncoding);
                                      settings.setEncodingMode(m_mainWindow->constantQualityRadioButton().isChecked() ?
                                                               QMultimedia::ConstantQualityEncoding :
                                                               QMultimedia::ConstantBitRateEncoding);
                              
                                      QString container = boxValue(ui->containerBox).toString();
                              
                                      m_audioRecorder->setEncodingSettings(settings, QVideoEncoderSettings(), container);
                                      m_audioRecorder->record();
                                  }
                                  else {
                                      m_audioRecorder->stop();
                                  }
                              }
                              
                              void AudioRecorder::togglePause()
                              {
                                  if (m_audioRecorder->state() != QMediaRecorder::PausedState)
                                      m_audioRecorder->pause();
                                  else
                                      m_audioRecorder->record();
                              }
                              
                              void AudioRecorder::setOutputLocation()
                              {
                              #ifdef Q_OS_WINRT
                                  // UWP does not allow to store outside the sandbox
                                  const QString cacheDir = QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
                                  if (!QDir().mkpath(cacheDir)) {
                                      qWarning() << "Failed to create cache directory";
                                      return;
                                  }
                                  QString fileName = cacheDir + QLatin1String("/output.wav");
                              #else
                                  QString fileName = QFileDialog::getSaveFileName();
                              #endif
                                  m_audioRecorder->setOutputLocation(QUrl::fromLocalFile(fileName));
                                  m_outputLocationSet = true;
                              }
                              
                              
                              void AudioRecorder::displayErrorMessage()
                              {
                                  //ui->statusbar->showMessage(m_audioRecorder->errorString());
                                  m_mainWindow->statusbar().showMessage(m_audioRecorder->errorString());
                              }
                              
                              void AudioRecorder::clearAudioLevels()
                              {
                                  for (int i = 0; i < m_audioLevels.size(); ++i)
                                      m_audioLevels.at(i)->setLevel(0);
                              }
                              
                              // This function returns the maximum possible sample value for a given audio format
                              qreal getPeakValue(const QAudioFormat& format)
                              {
                                  // Note: Only the most common sample formats are supported
                                  if (!format.isValid())
                                      return qreal(0);
                              
                                  if (format.codec() != "audio/pcm")
                                      return qreal(0);
                              
                                  switch (format.sampleType()) {
                                  case QAudioFormat::Unknown:
                                      break;
                                  case QAudioFormat::Float:
                                      if (format.sampleSize() != 32) // other sample formats are not supported
                                          return qreal(0);
                                      return qreal(1.00003);
                                  case QAudioFormat::SignedInt:
                                      if (format.sampleSize() == 32)
                                          return qreal(INT_MAX);
                                      if (format.sampleSize() == 16)
                                          return qreal(SHRT_MAX);
                                      if (format.sampleSize() == 8)
                                          return qreal(CHAR_MAX);
                                      break;
                                  case QAudioFormat::UnSignedInt:
                                      if (format.sampleSize() == 32)
                                          return qreal(UINT_MAX);
                                      if (format.sampleSize() == 16)
                                          return qreal(USHRT_MAX);
                                      if (format.sampleSize() == 8)
                                          return qreal(UCHAR_MAX);
                                      break;
                                  }
                              
                                  return qreal(0);
                              }
                              
                              // returns the audio level for each channel
                              QVector<qreal> getBufferLevels(const QAudioBuffer& buffer)
                              {
                                  QVector<qreal> values;
                              
                                  if (!buffer.format().isValid() || buffer.format().byteOrder() != QAudioFormat::LittleEndian)
                                      return values;
                              
                                  if (buffer.format().codec() != "audio/pcm")
                                      return values;
                              
                                  int channelCount = buffer.format().channelCount();
                                  values.fill(0, channelCount);
                                  qreal peak_value = getPeakValue(buffer.format());
                                  if (qFuzzyCompare(peak_value, qreal(0)))
                                      return values;
                              
                                  switch (buffer.format().sampleType()) {
                                  case QAudioFormat::Unknown:
                                  case QAudioFormat::UnSignedInt:
                                      if (buffer.format().sampleSize() == 32)
                                          values = getBufferLevels(buffer.constData<quint32>(), buffer.frameCount(), channelCount);
                                      if (buffer.format().sampleSize() == 16)
                                          values = getBufferLevels(buffer.constData<quint16>(), buffer.frameCount(), channelCount);
                                      if (buffer.format().sampleSize() == 8)
                                          values = getBufferLevels(buffer.constData<quint8>(), buffer.frameCount(), channelCount);
                                      for (int i = 0; i < values.size(); ++i)
                                          values[i] = qAbs(values.at(i) - peak_value / 2) / (peak_value / 2);
                                      break;
                                  case QAudioFormat::Float:
                                      if (buffer.format().sampleSize() == 32) {
                                          values = getBufferLevels(buffer.constData<float>(), buffer.frameCount(), channelCount);
                                          for (int i = 0; i < values.size(); ++i)
                                              values[i] /= peak_value;
                                      }
                                      break;
                                  case QAudioFormat::SignedInt:
                                      if (buffer.format().sampleSize() == 32)
                                          values = getBufferLevels(buffer.constData<qint32>(), buffer.frameCount(), channelCount);
                                      if (buffer.format().sampleSize() == 16)
                                          values = getBufferLevels(buffer.constData<qint16>(), buffer.frameCount(), channelCount);
                                      if (buffer.format().sampleSize() == 8)
                                          values = getBufferLevels(buffer.constData<qint8>(), buffer.frameCount(), channelCount);
                                      for (int i = 0; i < values.size(); ++i)
                                          values[i] /= peak_value;
                                      break;
                                  }
                              
                                  return values;
                              }
                              
                              template <class T>
                              QVector<qreal> getBufferLevels(const T *buffer, int frames, int channels)
                              {
                                  QVector<qreal> max_values;
                                  max_values.fill(0, channels);
                              
                                  for (int i = 0; i < frames; ++i) {
                                      for (int j = 0; j < channels; ++j) {
                                          qreal value = qAbs(qreal(buffer[i * channels + j]));
                                          if (value > max_values.at(j))
                                              max_values.replace(j, value);
                                      }
                                  }
                              
                                  return max_values;
                              }
                              
                              void AudioRecorder::processBuffer(const QAudioBuffer& buffer)
                              {
                                  if (m_audioLevels.count() != buffer.format().channelCount()) {
                                      qDeleteAll(m_audioLevels);
                                      m_audioLevels.clear();
                                      for (int i = 0; i < buffer.format().channelCount(); ++i) {
                                          AudioLevel *level = new AudioLevel(ui->centralwidget);
                                          m_audioLevels.append(level);
                                          //ui->levelsLayout->addWidget(level);
                                          m_mainWindow->levelsLayout().addWidget(level);
                                      }
                                  }
                              
                                  QVector<qreal> levels = getBufferLevels(buffer);
                                  for (int i = 0; i < levels.count(); ++i)
                                      m_audioLevels.at(i)->setLevel(levels.at(i));
                              }
                              
                              
                              
                              JonBJ Offline
                              JonBJ Offline
                              JonB
                              wrote on last edited by JonB
                              #15

                              @MHage said in Zugriff auf Methoden anderer Klassen:

                              audiorecorder.cpp

                              #include "mainwindow.h"
                              #include "ui_mainwindow.h"

                              Zusätzlich: Sie sollten nicht mainwindow.h, und sicher nicht ui_mainwindow.h, in jeder Datei außer mainwindow.cpp inkludieren.

                              m_mainWindow->statusbar().showMessage(statusMessage);

                              Eine Möglichkeit besteht darin, stattdessen ein Signal zu senden.

                              1 Reply Last reply
                              2
                              • M MHage

                                Das lässt hoffen. Ich habe nämlich komplett den Faden verloren...

                                mainwindow.h

                                #ifndef MAINWINDOW_H
                                #define MAINWINDOW_H
                                
                                #include <QMainWindow>
                                #include <QUrl>
                                #include <QDir>
                                #include <QFileDialog>
                                #include <QStandardPaths>
                                #include <QObject>
                                #include <QMultimedia>
                                #include <QAudioRecorder>
                                #include <QMediaRecorder>
                                #include <QSlider>
                                #include <QRadioButton>
                                
                                #include "audiodevicesbase.h"
                                #include "audiorecorder.h"
                                
                                QT_BEGIN_NAMESPACE
                                namespace Ui { class MainWindow; }
                                QT_END_NAMESPACE
                                
                                class MainWindow : public QMainWindow
                                {
                                    Q_OBJECT
                                
                                public:
                                    MainWindow(QWidget *parent = nullptr);
                                        ~MainWindow();
                                
                                public slots:
                                    QStatusBar statusbar();
                                    QPushButton recordButton();
                                    QPushButton pauseButton();
                                    QComboBox *bitrateBox();
                                    QVBoxLayout levelsLayout();
                                    QSlider qualitySlider();
                                    QRadioButton constantQualityRadioButton();
                                
                                
                                private slots:
                                    void on_pushButton_clicked();
                                    void on_actionAufnahmeparameter_triggered();
                                
                                
                                
                                private:
                                    Ui::MainWindow *ui;
                                    AudioRecorder *m_audioRecorder = nullptr;
                                    void clearAudioLevels();
                                
                                };
                                #endif // MAINWINDOW_H
                                
                                

                                mainwoindow.cpp

                                #include "mainwindow.h"
                                #include "ui_mainwindow.h"
                                
                                
                                
                                MainWindow::MainWindow(QWidget *parent)
                                    : QMainWindow(parent)
                                    , ui(new Ui::MainWindow)
                                {
                                    ui->setupUi(this);
                                    m_audioRecorder = new QAudioRecorder(AudioRecorder);
                                
                                    //connect(ui->constantQualityRadioButton, &QRadioButton::toggled, this, &MainWindow::setEnabled);
                                    //connect(ui->constantBitrateRadioButton, &QRadioButton::toggled, this, &MainWindow::setEnabled);
                                
                                    //Q_ASSUME(connect(ui->actionSpeichern, &QMenuBar::triggered, audioRecorder, &AudioRecorder::setOutputLocation));
                                    Q_ASSUME(connect(ui->outputButton, &QPushButton::clicked, m_audioRecorder, &AudioRecorder::setOutputLocation));
                                    Q_ASSUME(connect(ui->recordButton, &QPushButton::clicked, m_audioRecorder, &AudioRecorder::toggleRecord));
                                    Q_ASSUME(connect(ui->pauseButton, &QPushButton::clicked, m_audioRecorder, &AudioRecorder::togglePause));
                                
                                    //quality
                                    ui->qualitySlider->setRange(0, int(QMultimedia::VeryHighQuality));
                                    ui->qualitySlider->setValue(int(QMultimedia::NormalQuality));
                                
                                    //bitrates:
                                    ui->bitrateBox->addItem(tr("Default"), QVariant(0));
                                    ui->bitrateBox->addItem(QStringLiteral("32000"), QVariant(32000));
                                    ui->bitrateBox->addItem(QStringLiteral("64000"), QVariant(64000));
                                    ui->bitrateBox->addItem(QStringLiteral("96000"), QVariant(96000));
                                    ui->bitrateBox->addItem(QStringLiteral("128000"), QVariant(128000));
                                }
                                
                                
                                MainWindow::~MainWindow()
                                {
                                    delete ui;
                                    delete m_audioRecorder;
                                }
                                

                                audiorecorder.h

                                #ifndef AUDIORECORDER_H
                                #define AUDIORECORDER_H
                                
                                #include <QUrl>
                                #include <QAudioProbe>
                                #include <QAudioRecorder>
                                #include <QMediaRecorder>
                                #include <QDir>
                                #include <QFileDialog>
                                #include <QStandardPaths>
                                #include <QDialog>
                                
                                #include "mainwindow.h"
                                
                                
                                QT_BEGIN_NAMESPACE
                                namespace Ui { class AudioRecorder; }
                                class QAudioRecorder;
                                class QAudioProbe;
                                class QAudioBuffer;
                                QT_END_NAMESPACE
                                
                                class AudioLevel;
                                
                                
                                class AudioRecorder : public QDialog
                                {
                                    Q_OBJECT
                                
                                public:
                                    explicit AudioRecorder(QWidget *parent = nullptr);
                                    ~AudioRecorder();
                                
                                public slots:
                                    void processBuffer(const QAudioBuffer&);
                                
                                    void setOutputLocation();
                                    void togglePause();
                                    void toggleRecord();
                                
                                    void updateStatus(QMediaRecorder::Status);
                                    void onStateChanged(QMediaRecorder::State);
                                    void updateProgress(qint64 pos);
                                    void displayErrorMessage();
                                
                                private slots:
                                
                                
                                private:
                                
                                    QAudioRecorder *m_audioRecorder = nullptr;
                                    bool m_outputLocationSet = false;
                                    QAudioProbe *m_probe = nullptr;
                                    QList<AudioLevel*> m_audioLevels;
                                
                                    void clearAudioLevels();
                                    MainWindow *m_mainWindow = nullptr;
                                
                                    Ui::AudioRecorder *ui = nullptr;
                                };
                                
                                #endif // AUDIORECORDER_H
                                
                                

                                audiorecorder.cpp

                                #include "audiorecorder.h"
                                #include "audiolevel.h"
                                #include "ui_audiorecorder.h"
                                
                                #include "mainwindow.h"
                                #include "ui_mainwindow.h"
                                
                                static qreal getPeakValue(const QAudioFormat &format);
                                static QVector<qreal> getBufferLevels(const QAudioBuffer &buffer);
                                
                                template <class T>
                                static QVector<qreal> getBufferLevels(const T *buffer, int frames, int channels);
                                
                                AudioRecorder::AudioRecorder(QWidget *parent) :
                                    QDialog(parent),
                                    ui(new Ui::AudioRecorder)
                                {
                                    ui->setupUi(this);
                                
                                    m_audioRecorder = new QAudioRecorder(this);
                                    m_probe = new QAudioProbe(this);
                                    connect(m_probe, &QAudioProbe::audioBufferProbed, this, &AudioRecorder::processBuffer);
                                    m_probe->setSource(m_audioRecorder);
                                
                                    m_mainWindow = new QMainWindow(MainWindow);
                                
                                    //audio devices
                                    ui->audioDeviceBox->addItem(tr("Default"), QVariant(QString()));
                                    for (auto &device: m_audioRecorder->audioInputs()) {
                                        ui->audioDeviceBox->addItem(device, QVariant(device));
                                    }
                                
                                    //audio codecs
                                    ui->audioCodecBox->addItem(tr("Default"), QVariant(QString()));
                                    for (auto &codecName: m_audioRecorder->supportedAudioCodecs()) {
                                        ui->audioCodecBox->addItem(codecName, QVariant(codecName));
                                    }
                                
                                    //containers
                                    ui->containerBox->addItem(tr("Default"), QVariant(QString()));
                                    for (auto &containerName: m_audioRecorder->supportedContainers()) {
                                        ui->containerBox->addItem(containerName, QVariant(containerName));
                                    }
                                
                                    //sample rate
                                    ui->sampleRateBox->addItem(tr("Default"), QVariant(0));
                                    for (int sampleRate: m_audioRecorder->supportedAudioSampleRates()) {
                                        ui->sampleRateBox->addItem(QString::number(sampleRate), QVariant(
                                                sampleRate));
                                    }
                                
                                    //channels
                                    ui->channelsBox->addItem(tr("Default"), QVariant(-1));
                                    ui->channelsBox->addItem(QStringLiteral("1"), QVariant(1));
                                    ui->channelsBox->addItem(QStringLiteral("2"), QVariant(2));
                                    ui->channelsBox->addItem(QStringLiteral("4"), QVariant(4));
                                
                                    /*
                                    //quality
                                    ui->qualitySlider->setRange(0, int(QMultimedia::VeryHighQuality));
                                    ui->qualitySlider->setValue(int(QMultimedia::NormalQuality));
                                
                                    //bitrates:
                                    ui->bitrateBox->addItem(tr("Default"), QVariant(0));
                                    ui->bitrateBox->addItem(QStringLiteral("32000"), QVariant(32000));
                                    ui->bitrateBox->addItem(QStringLiteral("64000"), QVariant(64000));
                                    ui->bitrateBox->addItem(QStringLiteral("96000"), QVariant(96000));
                                    ui->bitrateBox->addItem(QStringLiteral("128000"), QVariant(128000));
                                    */
                                
                                    connect(m_audioRecorder, &QAudioRecorder::durationChanged, this, &AudioRecorder::updateProgress);
                                    connect(m_audioRecorder, &QAudioRecorder::durationChanged, this, &AudioRecorder::updateProgress);
                                    connect(m_audioRecorder, &QAudioRecorder::statusChanged, this, &AudioRecorder::updateStatus);
                                    connect(m_audioRecorder, &QAudioRecorder::stateChanged, this, &AudioRecorder::onStateChanged);
                                    connect(m_audioRecorder, QOverload<QMediaRecorder::Error>::of(&QAudioRecorder::error), this, &AudioRecorder::displayErrorMessage);
                                }
                                
                                AudioRecorder::~AudioRecorder()
                                {
                                    delete ui;
                                    delete m_mainWindow;
                                }
                                
                                
                                void AudioRecorder::updateProgress(qint64 duration)
                                {
                                    if (m_audioRecorder->error() != QMediaRecorder::NoError || duration < 2000)
                                        return;
                                
                                    //ui->statusbar->showMessage(tr("Recorded %1 sec").arg(duration / 1000));
                                    m_mainWindow->statusbar().showMessage(tr("Recorded %1 sec").arg(duration / 1000));
                                }
                                
                                void AudioRecorder::updateStatus(QMediaRecorder::Status status)
                                {
                                    QString statusMessage;
                                
                                    switch (status) {
                                    case QMediaRecorder::RecordingStatus:
                                        statusMessage = tr("Recording to %1").arg(m_audioRecorder->actualLocation().toString());
                                        break;
                                    case QMediaRecorder::PausedStatus:
                                        clearAudioLevels();
                                        statusMessage = tr("Paused");
                                        break;
                                    case QMediaRecorder::UnloadedStatus:
                                    case QMediaRecorder::LoadedStatus:
                                        clearAudioLevels();
                                        statusMessage = tr("Stopped");
                                    default:
                                        break;
                                    }
                                
                                    if (m_audioRecorder->error() == QMediaRecorder::NoError)
                                        //ui->statusbar->showMessage(statusMessage);
                                        m_mainWindow->statusbar().showMessage(statusMessage);
                                }
                                
                                void AudioRecorder::onStateChanged(QMediaRecorder::State state)
                                {
                                    switch (state) {
                                    case QMediaRecorder::RecordingState:
                                        //ui->recordButton->setText(tr("Stop"));
                                        //ui->pauseButton->setText(tr("Pause"));
                                        m_mainWindow->recordButton().setText(tr("Stop"));
                                        m_mainWindow->pauseButton().setText(tr("Pause"));
                                        break;
                                    case QMediaRecorder::PausedState:
                                        //ui->recordButton->setText(tr("Stop"));
                                        //ui->pauseButton->setText(tr("Resume"));
                                        m_mainWindow->recordButton().setText(tr("Stop"));
                                        m_mainWindow->pauseButton().setText(tr("Resume"));
                                        break;
                                    case QMediaRecorder::StoppedState:
                                        //ui->recordButton->setText(tr("Record"));
                                        //ui->pauseButton->setText(tr("Pause"));
                                        m_mainWindow->recordButton().setText(tr("Stop"));
                                        m_mainWindow->pauseButton().setText(tr("Pause"));
                                        break;
                                    }
                                
                                    //ui->pauseButton->setEnabled(m_audioRecorder->state() != QMediaRecorder::StoppedState);
                                    m_mainWindow->pauseButton().setEnabled(m_audioRecorder->state() != QMediaRecorder::StoppedState);
                                }
                                
                                static QVariant boxValue(const QComboBox *box)
                                {
                                    int idx = box->currentIndex();
                                    if (idx == -1)
                                        return QVariant();
                                
                                    return box->itemData(idx);
                                }
                                
                                void AudioRecorder::toggleRecord()
                                {
                                    if (m_audioRecorder->state() == QMediaRecorder::StoppedState) {
                                        m_audioRecorder->setAudioInput(boxValue(ui->audioDeviceBox).toString());
                                
                                        QAudioEncoderSettings settings;
                                        settings.setCodec(boxValue(ui->audioCodecBox).toString());
                                        settings.setSampleRate(boxValue(ui->sampleRateBox).toInt());
                                        //settings.setBitRate(boxValue(ui->bitrateBox).toInt());
                                        settings.setBitRate(boxValue(m_mainWindow->bitrateBox()).toInt());
                                
                                        settings.setChannelCount(boxValue(ui->channelsBox).toInt());
                                        //settings.setQuality(QMultimedia::EncodingQuality(ui->qualitySlider->value()));
                                        settings.setQuality(QMultimedia::EncodingQuality(m_mainWindow->qualitySlider().value()));
                                        //settings.setEncodingMode(ui->constantQualityRadioButton->isChecked() ?
                                        //                         QMultimedia::ConstantQualityEncoding :
                                        //                         QMultimedia::ConstantBitRateEncoding);
                                        settings.setEncodingMode(m_mainWindow->constantQualityRadioButton().isChecked() ?
                                                                 QMultimedia::ConstantQualityEncoding :
                                                                 QMultimedia::ConstantBitRateEncoding);
                                
                                        QString container = boxValue(ui->containerBox).toString();
                                
                                        m_audioRecorder->setEncodingSettings(settings, QVideoEncoderSettings(), container);
                                        m_audioRecorder->record();
                                    }
                                    else {
                                        m_audioRecorder->stop();
                                    }
                                }
                                
                                void AudioRecorder::togglePause()
                                {
                                    if (m_audioRecorder->state() != QMediaRecorder::PausedState)
                                        m_audioRecorder->pause();
                                    else
                                        m_audioRecorder->record();
                                }
                                
                                void AudioRecorder::setOutputLocation()
                                {
                                #ifdef Q_OS_WINRT
                                    // UWP does not allow to store outside the sandbox
                                    const QString cacheDir = QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
                                    if (!QDir().mkpath(cacheDir)) {
                                        qWarning() << "Failed to create cache directory";
                                        return;
                                    }
                                    QString fileName = cacheDir + QLatin1String("/output.wav");
                                #else
                                    QString fileName = QFileDialog::getSaveFileName();
                                #endif
                                    m_audioRecorder->setOutputLocation(QUrl::fromLocalFile(fileName));
                                    m_outputLocationSet = true;
                                }
                                
                                
                                void AudioRecorder::displayErrorMessage()
                                {
                                    //ui->statusbar->showMessage(m_audioRecorder->errorString());
                                    m_mainWindow->statusbar().showMessage(m_audioRecorder->errorString());
                                }
                                
                                void AudioRecorder::clearAudioLevels()
                                {
                                    for (int i = 0; i < m_audioLevels.size(); ++i)
                                        m_audioLevels.at(i)->setLevel(0);
                                }
                                
                                // This function returns the maximum possible sample value for a given audio format
                                qreal getPeakValue(const QAudioFormat& format)
                                {
                                    // Note: Only the most common sample formats are supported
                                    if (!format.isValid())
                                        return qreal(0);
                                
                                    if (format.codec() != "audio/pcm")
                                        return qreal(0);
                                
                                    switch (format.sampleType()) {
                                    case QAudioFormat::Unknown:
                                        break;
                                    case QAudioFormat::Float:
                                        if (format.sampleSize() != 32) // other sample formats are not supported
                                            return qreal(0);
                                        return qreal(1.00003);
                                    case QAudioFormat::SignedInt:
                                        if (format.sampleSize() == 32)
                                            return qreal(INT_MAX);
                                        if (format.sampleSize() == 16)
                                            return qreal(SHRT_MAX);
                                        if (format.sampleSize() == 8)
                                            return qreal(CHAR_MAX);
                                        break;
                                    case QAudioFormat::UnSignedInt:
                                        if (format.sampleSize() == 32)
                                            return qreal(UINT_MAX);
                                        if (format.sampleSize() == 16)
                                            return qreal(USHRT_MAX);
                                        if (format.sampleSize() == 8)
                                            return qreal(UCHAR_MAX);
                                        break;
                                    }
                                
                                    return qreal(0);
                                }
                                
                                // returns the audio level for each channel
                                QVector<qreal> getBufferLevels(const QAudioBuffer& buffer)
                                {
                                    QVector<qreal> values;
                                
                                    if (!buffer.format().isValid() || buffer.format().byteOrder() != QAudioFormat::LittleEndian)
                                        return values;
                                
                                    if (buffer.format().codec() != "audio/pcm")
                                        return values;
                                
                                    int channelCount = buffer.format().channelCount();
                                    values.fill(0, channelCount);
                                    qreal peak_value = getPeakValue(buffer.format());
                                    if (qFuzzyCompare(peak_value, qreal(0)))
                                        return values;
                                
                                    switch (buffer.format().sampleType()) {
                                    case QAudioFormat::Unknown:
                                    case QAudioFormat::UnSignedInt:
                                        if (buffer.format().sampleSize() == 32)
                                            values = getBufferLevels(buffer.constData<quint32>(), buffer.frameCount(), channelCount);
                                        if (buffer.format().sampleSize() == 16)
                                            values = getBufferLevels(buffer.constData<quint16>(), buffer.frameCount(), channelCount);
                                        if (buffer.format().sampleSize() == 8)
                                            values = getBufferLevels(buffer.constData<quint8>(), buffer.frameCount(), channelCount);
                                        for (int i = 0; i < values.size(); ++i)
                                            values[i] = qAbs(values.at(i) - peak_value / 2) / (peak_value / 2);
                                        break;
                                    case QAudioFormat::Float:
                                        if (buffer.format().sampleSize() == 32) {
                                            values = getBufferLevels(buffer.constData<float>(), buffer.frameCount(), channelCount);
                                            for (int i = 0; i < values.size(); ++i)
                                                values[i] /= peak_value;
                                        }
                                        break;
                                    case QAudioFormat::SignedInt:
                                        if (buffer.format().sampleSize() == 32)
                                            values = getBufferLevels(buffer.constData<qint32>(), buffer.frameCount(), channelCount);
                                        if (buffer.format().sampleSize() == 16)
                                            values = getBufferLevels(buffer.constData<qint16>(), buffer.frameCount(), channelCount);
                                        if (buffer.format().sampleSize() == 8)
                                            values = getBufferLevels(buffer.constData<qint8>(), buffer.frameCount(), channelCount);
                                        for (int i = 0; i < values.size(); ++i)
                                            values[i] /= peak_value;
                                        break;
                                    }
                                
                                    return values;
                                }
                                
                                template <class T>
                                QVector<qreal> getBufferLevels(const T *buffer, int frames, int channels)
                                {
                                    QVector<qreal> max_values;
                                    max_values.fill(0, channels);
                                
                                    for (int i = 0; i < frames; ++i) {
                                        for (int j = 0; j < channels; ++j) {
                                            qreal value = qAbs(qreal(buffer[i * channels + j]));
                                            if (value > max_values.at(j))
                                                max_values.replace(j, value);
                                        }
                                    }
                                
                                    return max_values;
                                }
                                
                                void AudioRecorder::processBuffer(const QAudioBuffer& buffer)
                                {
                                    if (m_audioLevels.count() != buffer.format().channelCount()) {
                                        qDeleteAll(m_audioLevels);
                                        m_audioLevels.clear();
                                        for (int i = 0; i < buffer.format().channelCount(); ++i) {
                                            AudioLevel *level = new AudioLevel(ui->centralwidget);
                                            m_audioLevels.append(level);
                                            //ui->levelsLayout->addWidget(level);
                                            m_mainWindow->levelsLayout().addWidget(level);
                                        }
                                    }
                                
                                    QVector<qreal> levels = getBufferLevels(buffer);
                                    for (int i = 0; i < levels.count(); ++i)
                                        m_audioLevels.at(i)->setLevel(levels.at(i));
                                }
                                
                                
                                
                                Pl45m4P Online
                                Pl45m4P Online
                                Pl45m4
                                wrote on last edited by Pl45m4
                                #16

                                @MHage

                                So wie ich das sehe, gibt es auch gar keinen Grund m_mainWindow in AudioRecorder zu haben. Wie @JonB sagte, für alle Zugriffe auf die UI bzw. das MainWindow besser Signale senden und die Änderung in deiner MainWindow Klasse durchführen.

                                Deine Destruktoren sind nämlich auch nicht ganz so toll :)

                                MainWindow::~MainWindow()
                                {
                                    delete ui;
                                    delete m_audioRecorder;
                                }
                                
                                AudioRecorder::~AudioRecorder()
                                {
                                    delete ui;
                                    delete m_mainWindow;
                                }
                                

                                Das sollte, je nach Parent-Child-Struktur, eigentlich immer irgendwann zu einem Crash führen.


                                If debugging is the process of removing software bugs, then programming must be the process of putting them in.

                                ~E. W. Dijkstra

                                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