androidqtaudioqml

SoundEffect does not play a WAV soundeffect on android


I have recently added support for the sound effects replay in my Qt application and ported it to android platform.

For playing my sound file I used a MediaPlayer QML component, which was able to play my effect, but was useless for frequent sound, thus I needed a more efficient component, which would replay the sound effect with small latencies.

According to Qt's documentation, the SoundEffect should be the first choice, but for some reason the sound is not playing.

In my debug status output I can see that when SoundEffect.play() is triggered the playing is set to true, but then immediately reset to false. In the console output I can see this messages:

W QtAudioDeviceManager: Built in Earpiece may not work when Wired Headphones are connected
D AudioManager: setMode mode=2 from com.indurad.ioau
I AudioManager: In stopBluetoothSco(), calling application: com.indurad.ioau
I AudioManager: In setBluetoothScoOn(), on: false, calling application: com.indurad.ioau
I AudioManager: In setSpeakerphoneOn(), on: false, calling application: com.indurad.ioau
D om.indurad.ioa: PlayerBase::PlayerBase()
D om.indurad.ioa: TrackPlayerBase::TrackPlayerBase()
I libOpenSLES: android_audioPlayer_realize, channel mask 0x3
I libOpenSLES: android_audioPlayer_realize, create default channel mask 0x3, channels 2
I libOpenSLES: Emulating old channel mask behavior (ignoring positional mask 0x3, using default mask 0x3 based on channel count of 2)
D AudioTrackExtImpl: AudioTrackExtImpl init
D AudioTrack: set() streamType 3, sampleRate 24000, format 0x1, channelMask 0x3, frameCount 0, flags #104, notificationFrames -2, sessionId 1673, transferType 0, uid -1, pid -1 cbf 1
E AudioSystem: invalid attributes { Content type: AUDIO_CONTENT_TYPE_UNKNOWN Usage: AUDIO_USAGE_UNKNOWN Source: AUDIO_SOURCE_DEFAULT Flags: 0x0 Tags:  } when converting to stream
D AudioTrack: createTrack_l(0): AUDIO_OUTPUT_FLAG_FAST denied by server; frameCount 0 -> 968
I AudioTrack: createTrack_l(2091) on outputId(13) : 0x70a15a1400, mCblk = 0x721b6cc000,  mLatency = 88, mAfLatency = 48, frameCount = 968, mSampleRate = 24000, mFlags = 0, mReqFrameCount = 968, mNotificationFramesAct = 480
D ListServiceUtils: mListServiceUtils::init CallingPid 32492
D ListServiceUtils: mListServiceUtils::init this 0x70be56c740
D AudioTrack: setVolume left 0.000 right 0.000 , callingPid 32492
D AudioTrack: start(2091): prior state:STATE_STOPPED output 13 stream 3 session 1673
D om.indurad.ioa: PlayerBase::stop() from IPlayer
D AudioTrack: stop(2091): prior state:STATE_ACTIVE output 13 stream 3 session 1673
D AudioTrack: stop(2091): called with 2400 frames delivered
D AudioTrack: flush(2091): prior state:STATE_STOPPED
D AudioTrack: start(2091): prior state:STATE_FLUSHED output 13 stream 3 session 1673
D om.indurad.ioa: PlayerBase::stop() from IPlayer
D AudioTrack: stop(2091): prior state:STATE_ACTIVE output 13 stream 3 session 1673
D AudioTrack: stop(2091): called with 2400 frames delivered
D AudioTrack: flush(2091): prior state:STATE_STOPPED
D AudioTrack: start(2091): prior state:STATE_FLUSHED output 13 stream 3 session 1673
D om.indurad.ioa: PlayerBase::stop() from IPlayer
D AudioTrack: stop(2091): prior state:STATE_ACTIVE output 13 stream 3 session 1673
D AudioTrack: stop(2091): called with 4328 frames delivered
D AudioTrack: flush(2091): prior state:STATE_STOPPED
D AudioTrack: start(2091): prior state:STATE_FLUSHED output 13 stream 3 session 1673
D om.indurad.ioa: PlayerBase::stop() from IPlayer
D AudioTrack: stop(2091): prior state:STATE_ACTIVE output 13 stream 3 session 1673
D AudioTrack: stop(2091): called with 4328 frames delivered
D AudioTrack: flush(2091): prior state:STATE_STOPPED
D AudioTrack: start(2091): prior state:STATE_FLUSHED output 13 stream 3 session 1673
D om.indurad.ioa: PlayerBase::stop() from IPlayer
D AudioTrack: stop(2091): prior state:STATE_ACTIVE output 13 stream 3 session 1673
D AudioTrack: stop(2091): called with 4320 frames delivered
D AudioTrack: flush(2091): prior state:STATE_STOPPED
D AudioTrack: setVolume left 1.000 right 1.000 , callingPid 32492

The message:

E AudioSystem: invalid attributes { Content type: AUDIO_CONTENT_TYPE_UNKNOWN Usage: AUDIO_USAGE_UNKNOWN Source: AUDIO_SOURCE_DEFAULT Flags: 0x0 Tags: } when converting to stream

led me to some articles, which say that the audio files should be supplied within the filesystem, but not the Qt resource system.

However, I am stuck a bit with how can one deploy assets to the android APK as is, without integrating them as Qt resources system.

I am using:

  • Qt 6.4.2
  • CMake for building android package.

Solution

  • [EDIT based on @musicamante comments]

    When it comes to understanding file formats, you have to realize that both the format and the inner stream codec are important.

    To demonstrate, I've tested a bunch of files with both MediaPlayer and SoundEffect.

    File Format Stream Windows
    MediaPlayer
    Android
    MediaPlayer
    Windows
    SoundEffect
    Android
    SoundEffect
    .wav pcm_s16le, 44100 Hz, stereo, s16, 1411 kb/s Yes Yes Yes Yes
    .mp3 mp3, 44100 Hz, stereo, fltp, 206 kb/s Yes Yes No No
    .mp2 mp2, 44100 Hz, stereo, s16 384 kb/s Yes Yes No No
    .ogg vorbis, 44100 Hz, stereo, fltp No Yes No No
    .ogg flac, 44100 Hz, stereo, s32 (24 bits), 128 kb/s No No No No

    There are are several observations from the above table:

      1. MediaPlayer plays more formats than SoundEffect. This is understood, since, SoundEffect is limited to uncompressed formats so that it can have lower latency.
      1. ogg/vorbis plays on Android but ogg/flac didn't. Reinforcing that having a container supported is not enough, you need to take care of the stream codec
      1. wav stereo 44100 Hz played successfully in all platforms tested

    The software I used to prepare the above files was ffmpeg, and the script I used was:

    ffmpeg -y -i test.wav test.mp3
    ffmpeg -y -i test.wav test.mp2
    ffmpeg -y -i test.wav -acodec libvorbis -vn test_ogg_vorbis.ogg
    ffmpeg -y -i test.wav -acodec flac      -vn test_ogg_flac.ogg