diff --git a/src/Document/CRTPSubDocument.cc b/src/Document/CRTPSubDocument.cc
new file mode 100644
index 0000000000000000000000000000000000000000..85983b5e5389a04d152ba1fe50efd10d09e387a7
--- /dev/null
+++ b/src/Document/CRTPSubDocument.cc
@@ -0,0 +1,73 @@
+#include "CRTPSubDocument.hh"
+
+using namespace Vivy;
+
+// AudioSubDocument implementation
+
+// Get the default stream index or -1 if not possible
+int
+AudioSubDocument::getDefaultStreamIndex() const noexcept
+{
+    if (auto ptr = getDefaultStream()) {
+        return ptr->getStreamIndex();
+    } else {
+        return -1;
+    }
+}
+
+// Get a pointer to the default stream, nullptr if not possible
+AudioContext::StreamPtr
+AudioSubDocument::getDefaultStream() const noexcept
+{
+    if (auto ptr = contextPtr->getDefaultStream().lock()) {
+        return ptr;
+    } else {
+        return nullptr;
+    }
+}
+
+// Get the stream count, may be 0
+int
+AudioSubDocument::getStreamCount() const noexcept
+{
+    return contextPtr->getStreamCount();
+}
+
+// Get the stream asked for, nullptr if no stream or if the index is invalid
+AudioContext::StreamPtr
+AudioSubDocument::getStream(int index) const noexcept
+{
+    if (auto ptr = contextPtr->getStream(index).lock()) {
+        return ptr;
+    } else {
+        return nullptr;
+    }
+}
+
+// Init an audio sub-document from a file
+void
+AudioSubDocument::initFromPath(const QString &path)
+{
+    if (contextPtr)
+        qDebug() << "Replacing the audio contetx by a new one for file" << path;
+    contextPtr.reset(new AudioContext(path)); // May throw
+
+    qDebug() << "Audio OK for" << path;
+}
+
+// VideoSubDocument implementation
+
+// Init a video sub-document from a file
+void
+VideoSubDocument::initFromPath(const QString &)
+{
+}
+
+// AssSubDocument implementation
+void
+AssSubDocument::initFromPath(const QString &path)
+{
+    Ass::AssFactory factory(path);
+    factory.getStyles(styles);
+    factory.getLines(lines);
+}
diff --git a/src/Document/CRTPSubDocument.hh b/src/Document/CRTPSubDocument.hh
index c3494adc343600e547b4ef803c55227ed79658ec..29b1c620eceb0e0c442b238a2d43ac37dd67cd13 100644
--- a/src/Document/CRTPSubDocument.hh
+++ b/src/Document/CRTPSubDocument.hh
@@ -64,20 +64,19 @@ class AudioSubDocument final : public CRTPSubDocument<AudioDocumentType, AudioSu
 private:
     const QStringList &suffixList = Vivy::Utils::audioFileSuffix;
 
-    inline void initFromPath(const QString &path)
-    {
-        if (contextPtr)
-            qDebug() << "Replacing the audio contetx by a new one for file" << path;
-        contextPtr.reset(new AudioContext(path)); // May throw
-
-        qDebug() << "Audio OK for" << path;
-    }
+    void initFromPath(const QString &);
 
     explicit AudioSubDocument() = default;
     friend CRTPSubDocument<AudioDocumentType, AudioSubDocument>;
 
 private:
     std::unique_ptr<AudioContext> contextPtr;
+
+public:
+    int getDefaultStreamIndex() const noexcept;
+    AudioContext::StreamPtr getDefaultStream() const noexcept;
+    int getStreamCount() const noexcept;
+    AudioContext::StreamPtr getStream(int index) const noexcept;
 };
 
 // Video document
@@ -85,9 +84,7 @@ class VideoSubDocument final : public CRTPSubDocument<VideoDocumentType, VideoSu
 private:
     const QStringList &suffixList = Vivy::Utils::videoFileSuffix;
 
-    inline void initFromPath([[maybe_unused]] const QString &path)
-    {
-    }
+    void initFromPath(const QString &);
 
     explicit VideoSubDocument() noexcept = default;
     friend CRTPSubDocument<VideoDocumentType, VideoSubDocument>;
@@ -97,12 +94,7 @@ private:
 class AssSubDocument final : public CRTPSubDocument<AssDocumentType, AssSubDocument> {
     const QStringList &suffixList = Vivy::Utils::assFileSuffix;
 
-    inline void initFromPath(const QString &path)
-    {
-        Ass::AssFactory factory(path);
-        factory.getStyles(styles);
-        factory.getLines(lines);
-    }
+    void initFromPath(const QString &);
 
     explicit AssSubDocument() noexcept = default;
     friend CRTPSubDocument<AssDocumentType, AssSubDocument>;
diff --git a/src/Lib/Audio.cc b/src/Lib/Audio.cc
index f163e7b898275fb0e582006fbbd1097d59744fea..65c1cdc856d01a6d6a8023dc87ea1925fd751c78 100644
--- a/src/Lib/Audio.cc
+++ b/src/Lib/Audio.cc
@@ -39,6 +39,12 @@ AudioContext::AudioContext(const QString &path)
         }
     }
 
+    // Get the default stream
+    defaultStreamIndex = av_find_best_stream(formatPtr, AVMEDIA_TYPE_AUDIO,
+                                             -1, // Let AV find one stream
+                                             -1, // We don't want related streams
+                                             nullptr, 0);
+
     qDebug() << "Opened audio context for" << path << "with duration" << formatPtr->duration;
 }
 
@@ -67,6 +73,16 @@ AudioContext::getStream(int index) const noexcept
     return StreamWeakPtr{ spareNullSreamPtr };
 }
 
+// Get the default stream of this audio context. If no default audio stream is
+// present you won't be able to lock the weak pointer.
+AudioContext::StreamWeakPtr
+AudioContext::getDefaultStream() const noexcept
+{
+    if (defaultStreamIndex < 0)
+        return StreamWeakPtr{ spareNullSreamPtr };
+    return getStream(defaultStreamIndex);
+}
+
 QString
 AudioContext::getElementName() const noexcept
 {
@@ -136,6 +152,12 @@ AudioContext::Stream::Stream(AVCodec *streamCodec, AVFormatContext *format, AVSt
     qDebug() << "[Stream] channels:   " << codecParams->channels;
 }
 
+AudioContext::Stream::~Stream() noexcept
+{
+    if (dataPtr)
+        free(dataPtr);
+}
+
 QJsonObject
 AudioContext::Stream::getProperties() const noexcept
 {
@@ -153,6 +175,7 @@ AudioContext::Stream::decodeData()
 {
     if (isDecoded())
         throw std::logic_error("audio stream is already resampled");
+    qDebug() << "Launch decoding of stream" << streamIndexInAudioContext;
 
     AVPacket packet;
     av_init_packet(&packet);
@@ -160,7 +183,7 @@ AudioContext::Stream::decodeData()
     // Iterate through frames
     while (av_read_frame(dataFormat, &packet) >= 0) {
         // Only decode audio
-        if (packet.stream_index == streamIndexInAudioContext) {
+        if (packet.stream_index != streamIndexInAudioContext) {
             av_packet_unref(&packet);
             continue;
         }
@@ -208,9 +231,9 @@ AudioContext::Stream::decodeData()
             // Append resampled frames to data
             else [[likely]] {
                 const size_t frame_count = static_cast<size_t>(frame_count_int);
-                dataRealPtr              = (double *)realloc(
-                    dataRealPtr, (dataSize + (size_t)dataFrame->nb_samples) * sizeof(double));
-                memcpy(dataRealPtr + dataSize, buffer, frame_count * sizeof(double));
+                dataPtr                  = reinterpret_cast<double *>(
+                    realloc(dataPtr, (dataSize + (size_t)dataFrame->nb_samples) * sizeof(double)));
+                memcpy(dataPtr + dataSize, buffer, frame_count * sizeof(double));
                 dataSize += frame_count;
             }
         }
@@ -218,15 +241,18 @@ AudioContext::Stream::decodeData()
         dataDeleter(buffer);
         av_packet_unref(&packet);
     }
+
+    qDebug() << "Decoding data finished for stream" << streamIndexInAudioContext
+             << "dataPtr =" << dataPtr << "with dataSize =" << dataSize;
 }
 
 // Delete decoded data, clean up thing
 void
 AudioContext::Stream::cleanUpData() noexcept
 {
-    dataPtr.reset();
-    dataRealPtr = nullptr;
-    dataSize    = 0;
+    free(dataPtr);
+    dataPtr  = nullptr;
+    dataSize = 0;
 }
 
 // Get the number of channels in the audio context stream
@@ -276,7 +302,7 @@ AudioContext::Stream::getBitRate() const noexcept
 bool
 AudioContext::Stream::isDecoded() const noexcept
 {
-    return dataPtr != nullptr && dataRealPtr != nullptr;
+    return dataPtr != nullptr;
 }
 
 // Get the decoded data's size, will return 0 if the data is not decoded. Don't
@@ -288,11 +314,30 @@ AudioContext::Stream::getDecodedDataSize() const noexcept
 }
 
 // Get the decoded data, safe to call even if the data is not decoded has the
-// weak pointer will be marked as already deleted (use_count will be 0 and
-// `(auto ptr = res.lock())` will be evaluated to false if inside an `if`
-// statement).
-AudioContext::Stream::DataWeakPtr
+// pointer will be null. You must check it with an `if` statement.
+double *
 AudioContext::Stream::getDecodedData() const noexcept
 {
-    return DataWeakPtr{ dataPtr };
+    return dataPtr;
+}
+
+// Get the chunk size of the decoded data
+size_t
+AudioContext::Stream::getDecodedChunkSize() const noexcept
+{
+    return 512;
+}
+
+// Get the decalage of the decoded data
+size_t
+AudioContext::Stream::getDecodedDecalage() const noexcept
+{
+    constexpr size_t overlap = 128; // The overlap
+    return getDecodedChunkSize() - overlap;
+}
+
+int
+AudioContext::Stream::getStreamIndex() const noexcept
+{
+    return streamIndexInAudioContext;
 }
diff --git a/src/Lib/Audio.hh b/src/Lib/Audio.hh
index ab6e9a13b36d6fbf348bce4aa5efb0a574de447b..72b67d288ea24fe93cf160e9f244ee4b7f733a75 100644
--- a/src/Lib/Audio.hh
+++ b/src/Lib/Audio.hh
@@ -64,7 +64,7 @@ public:
 
     public:
         Stream(AVCodec *, AVFormatContext *, AVStream *, int index);
-        ~Stream() = default;
+        ~Stream() noexcept;
 
         // The non-owning view of the stream's data
         using DataWeakPtr = std::weak_ptr<double[]>;
@@ -75,7 +75,9 @@ public:
         bool isDecoded() const noexcept;
         int getDataSampleRate() const noexcept;
         size_t getDecodedDataSize() const noexcept;
-        DataWeakPtr getDecodedData() const noexcept;
+        size_t getDecodedChunkSize() const noexcept;
+        size_t getDecodedDecalage() const noexcept;
+        double *getDecodedData() const noexcept;
 
         // Some getters
         int getChannels() const noexcept;
@@ -84,6 +86,9 @@ public:
         AVCodecID getCodecId() const noexcept;
         qint64 getBitRate() const noexcept;
 
+        // Get the index from the audio context
+        int getStreamIndex() const noexcept;
+
         QJsonObject getProperties() const noexcept;
 
     private:
@@ -103,8 +108,7 @@ public:
         AVFormatContext *dataFormat;
         SwrContextPtr dataSwrContext{ swr_alloc(), swrContenxtDeleter };
         AVFramePtr dataFrame{ av_frame_alloc(), avFrameDeleter };
-        DataPtr dataPtr{ nullptr, dataDeleter }; // Holds dataRealPtr
-        double *dataRealPtr{ nullptr };
+        double *dataPtr{ nullptr };
         size_t dataSize{ 0 };
 
         // Constants for the resampler
@@ -125,6 +129,7 @@ public:
 
     int getStreamCount() const noexcept;
     StreamWeakPtr getStream(int) const noexcept;
+    StreamWeakPtr getDefaultStream() const noexcept;
 
     QString getElementName() const noexcept;
     QJsonDocument getProperties() const noexcept;
@@ -143,6 +148,8 @@ private:
     QVector<uint> audioStreamIndexes{};   // Index all the audio streams of the file
     QMap<uint, StreamPtr> audioStreams{}; // THe audio streams of the file
 
+    int defaultStreamIndex{ -1 };
+
     // Spare always null shared pointer, to be used when the audioStream[i] was
     // not found.
     StreamPtr spareNullSreamPtr{ nullptr };