Mise en oeuvre du breakout “Adafruit I2S 3W Class D Amplifier” (→ MAC98357A)

Câblage

Configuration

  • Modifier le fichier /boot/config.txt comme suit :

    /boot/config.txt
    # [...]
    
    # Enable audio (loads snd_bcm2835)
    # MYIAQ2022 : Début config audio
    # ligne *commentée* pour mise en service du dac I2S
    # dtparam=audio=on
    # lignes *ajoutées* pour mise en service du dac I2S
    dtoverlay=hifiberry-dac
    dtoverlay=i2s-mmap
    # MYIAQ2022 : Fin config audio
    
    # [...]
  • Créer un nouveau fichier /etc/asound.conf avec le contenu suivant :

    /etc/asound.conf
    pcm.hifiberry {
        type hw card 0
    }
    
    pcm.!default {
        type plug
        slave.pcm "dmixer"
    }
    
    pcm.dmixer {
        type dmix
        ipc_key 1024
        slave {
            pcm "hifiberry"
            channels 2
        }
    }
  • Redémarrer la Raspberry Pi

Test depuis la ligne de commande

Pour tester la configuration, exécuter la commande suivante :

speaker-test -c2 --test=wav -w /usr/share/sounds/alsa/Front_Center.wav

On peut s’apercevoir qu’un son parasite est diffusé avant celui contenu dans le fichier audio.

Ce phénomène est bien expliqué dans l’article Adafruit MAX98357 I2S Class-D Mono Amp: Popping! link : il survient lors d’un changement brusque sur le signal PCM_CLK (→ GPIO18).

Pour y remédier, on peut se contenter de jouer en permanence sur la Raspberry Pi un “silence” avec la commande suivante :

aplay -t raw -f cd /dev/zero & (1)
1 Diffusion d’un silence (→ /dev/zero) avec une qualité CD (→ -f cd : freq. éch. 44100kHz, stéréo)

Ce silence sera rompu lors de la lecture d’un fichier audio mais sans variation brusque du signal PCM_CLK donc sans émission du bruit parasite.

Lecture d’un son depuis un programme Qt

  • Installer les paquets logiciels nécessaires :

    • qtmultimedia5-dev

      Ce paquet contient les fichiers de développement nécessaires pour générér des applications utilisant les librairies multimédia de Qt.

      Les paquets suivants seront installés par le biais des dépendances :

      • libglib2.0-dev

      • libpulse-dev

      • libqt5multimedia5

      • libqt5multimediagsttools5

      • libqt5multimediaquick5

      • libqt5multimediawidgets5

    • libqt5multimedia5-plugin

      Ce paquet résoud l’erreur “defaultServiceProvider::requestService(): no service found for - "org.qt-project.qt.mediaplayer"”

    • gstreamer1.0-pulseaudio

      Sans ce paquet, les programmes fonctionnent mais aucun son n’est produit quel que soit le format parmi les suivants : .wav, .mp3, .ogg.

  • Faire un programme Qt Console Application qui joue un son grâce à la classe QMediaPlayer

    Exemple

    → Archive contenant le projet Qt : test-i2s-audio.zip zip

    Fichier test-i2s-audio.pro
    QT -= gui
    QT += multimedia (1)
    
    CONFIG += c++11 console
    CONFIG -= app_bundle
    
    # The following define makes your compiler emit warnings if you use
    # any Qt feature that has been marked deprecated (the exact warnings
    # depend on your compiler). Please consult the documentation of the
    # deprecated API in order to know how to port your code away from it.
    DEFINES += QT_DEPRECATED_WARNINGS
    
    # You can also make your code fail to compile if it uses deprecated APIs.
    # In order to do so, uncomment the following line.
    # You can also select to disable deprecated APIs only up to a certain version of Qt.
    #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
    
    SOURCES += \
            main.cpp
    
    # Default rules for deployment.
    qnx: target.path = /tmp/$${TARGET}/bin
    else: unix:!android: target.path = /opt/$${TARGET}/bin
    !isEmpty(target.path): INSTALLS += target
    1 Ne pas oublier d’inclure le module multimedia
    main.cpp
    #include <QCoreApplication>
    #include <QObject>
    
    #include <QMediaPlayer>
    
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
    
        // Instanciation du lecteur audio
        QMediaPlayer * player = new QMediaPlayer;
    
        // Mise en place d'un slot qui permet d'afficher la progression de la
        // lecture du son (chargement, fin) et de quitter l'application après
        // sa lecture
        QObject::connect(player, &QMediaPlayer::stateChanged, [=]() {
            QMediaPlayer::MediaStatus state = player->mediaStatus();
            qDebug() << "status " << state;
            if (state == QMediaPlayer::EndOfMedia) {
                QCoreApplication::quit();
            }
        });
    
        // Spécification du son à jouer
        // (son récupéré sur https://lasonotheque.org/)
        player->setMedia(QUrl::fromLocalFile("/home/pi/Music/2153.wav"));
    
        // Réglage du volume sonore
        player->setVolume(50);
    
        // Lecture du son
        player->play();
    
        return a.exec();
    }

🞄  🞄  🞄