Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Play small Audio files without gaps



  • Hi,
    I need several small audio files to be played sequentially - but without gaps in between.
    I am using

            Audio {
                id: mediaPlayer
                playlist: Playlist {
                    id: playlist
                    PlaylistItem { source: "qrc:/snds/r1c1.wav"; }
                    PlaylistItem { source: "qrc:/snds/r1c2.wav"; }
                    PlaylistItem { source: "qrc:/snds/r1c3.wav"; }
                    playbackMode: Playlist.Sequential
                }
            }
    

    It does playback sequentially, but there's always a little gap (and some crackling) in between, that I do not get when I play the samples via Windows' "Media Player" playlist (so the samples are apparently ok).

    I have not found any setting for intentional gaps that I could set to zero. Are there better methods to play audio sequences? If necessary, I'd happily sidestep to a C++ solution, too, of course.

    I'd appreciate any hints or experiences on the matter!



  • @SeDi I tried it myself but I didnt notice any gaps between audiofiles. As soon as one of them finishes, it is passing to the other.
    If there are some gaps, it should be about miliseconds. Do u want that time to be exactly 0 sec?



  • @Yunus Thank you for your answer, yes, "exactly 0 s" ist crucial for my purpose. I try to implement a demonstration for Mozarts "Musikalisches Würfelspiel" (as described here) where a dice decides which of one of six possible next bars is played. So the bars have to be played seamlessly, like with no gap at all. When you use two "normal" tunes, you probably won't notice any gap between fadeout and intro.

    I could make it a bit better with a chain of SoundEffects:

    SoundEffect {
               id: bar1
               source: "qrc:/snds/r1c1.wav";
               onPlayingChanged: {
                   if (!playing) {
                       bar2.play()
                   }
               }
    
           }
    

    But it's still very audible. Any way to produce a seamless audio stream?



  • I have improved the situation a bit (not much) by using a chain of "SoundEffect" items as low latency option. Still, it was not really usable.

    Fortunately, my samples all have the exact same length, so I could find a hack that gets me set for the moment, I am calling the samples with a Timer and I use an interval that is very slightly (but not too disturbingly) shorter than the actual sample duration.

           Button {
                text: ("Play")
                onClicked: {
                    timer.bar = 1
                    timer.start()
                    bar1.play()
                }
            }
    
            SoundEffect { id: bar1 }
            SoundEffect { id: bar2 }
            SoundEffect { id: bar3 }
            SoundEffect { id: bar4 }
            SoundEffect { id: bar5 }
            SoundEffect { id: bar6 }
            SoundEffect { id: bar7 }
            SoundEffect { id: bar8 }
    
            SoundEffect { id: singlePlayBar }
    
            Timer {
                id: timer
                property int bar: 1
                interval: 1475 // instead of 1500
                onTriggered: {
                    bar++
                    switch (bar) {
                    case 1: bar1.play(); timer.restart(); break
                    case 2: bar2.play(); timer.restart(); break
                    case 3: bar3.play(); timer.restart(); break
                    case 4: bar4.play(); timer.restart(); break
                    case 5: bar5.play(); timer.restart(); break
                    case 6: bar6.play(); timer.restart(); break
                    case 7: bar7.play(); timer.restart(); break
                    case 8: bar8.play(); timer.restart(); break
                    }
                }
            }
    

    Now you can actually get the idea from the audio, but there are still some crackling sounds from time to time.

    Any ideas on how to concatenate wav-files into a seamless audio stream would be gratefully appreciated!



  • Do your samples have gaps/silence at the beginning or end of the file?



  • Perfectly valid question. Absolutely not. Extracted regions, directly from Soundforge. Triple checked this and rebuilt them anyway - to no avail...



  • @SeDi said in Play small Audio files without gaps:

    to no avail...

    Dang, I was hoping it was simple.
    One thing you could do is use 2 Audio objects and have one play and have the other track progress of the played sound. Then start playing the next one in the other Audio object when it gets to a certain percentage of being done. Maybe even mess with volume and do a fade in fade out if that makes sense at all. I looked at Audio and it has the ms progress and total ms and volume control. So it may be doable. Otherwise I think you might need to build a custom C++ object.



  • As I am dealing with a sequence of 8 bars of music, I am currently using 8 separate "SoundEffect" items that I trigger with a timer, because the gap was way too long (rythmically relevant) when triggering the respective next one with "onPlayingChanged".

    The idea to use the duration and position (with a sufficiently small notifyInterval) is cool. I could actually take longer samples and let them crossfade into another. Tricky, but probably quite doable. I'll have to look into that. Thank you for that idea, @fcarney !

    With "build a custom C++ object" you probably have something specific in mind, do you? I'd happily use C++ parts here, if that would be more suitable.



  • @SeDi said in Play small Audio files without gaps:

    you probably have something specific in mind, do you?

    Not really, I was just suggesting you might need to use C++ audio objects.



  • @SeDi
    Okay, I take that back. Are you looking for sound synthesis? I have played around with a library I modified to use with Qt. It can play samples I "think" but it also does sound synthesis. It is called Gamma. You can modify the threading to use QThread very easily.

    Fixed lib name.



  • Thanks, I'll definitely have a look into that. Synthesis is currently not my aim, but as a music teacher I am definitely interested in general. But, perhaps, SuperCollider could be a better language for that.

    I've built a small item that automatically fades itself in and out. It has further reduced the crackling while having no huge impact on attack, even before using longer samples with it. Not gone yet, but better.

    import QtQuick 2.13
    import QtMultimedia 5.13
    
    Item {
        id: fadeSoundEffectItem
        property int fadeDuration: 40
        Audio {
            id: playSound
            notifyInterval: 5
            onPositionChanged: {
                if ((duration - position) <= fadeDuration && !fadeOutAnimation.running)  {
                    fadeOutAnimation.duration = duration - playSound.position
                    fadeOutAnimation.start()
                }
    
            }
    
        }
        property alias source: playSound.source
        property real volume: 1
    
        PropertyAnimation {
            id: fadeInAnimation
            target: playSound
            property: "volume"
            to: fadeSoundEffectItem.volume
            duration: fadeDuration
            easing.type: Easing.Linear
        }
        PropertyAnimation {
            id: fadeOutAnimation
            target: playSound
            property: "volume"
            to: 0
            duration: duration - playSound.position
            easing.type: Easing.Linear
        }
        function fadeInAndPlay () {
            playSound.volume = 0;
            playSound.play()
            fadeInAnimation.start()
        }
        function play() { fadeInAndPlay() }
    }
    

    Edit: fixed code



  • I'll set this to solved, because I will not explore this further. Probably, a buffered audio stream (perhaps with QAudioOutput) would yield the cleanest result but as the result from fading is sufficient for my needs, I'll leave it there for now.

    Thanks for helping me!


Log in to reply