diff --git a/src/audio_core/hle/wmf_decoder.cpp b/src/audio_core/hle/wmf_decoder.cpp
index 92b53750c..3cb4ea1b2 100644
--- a/src/audio_core/hle/wmf_decoder.cpp
+++ b/src/audio_core/hle/wmf_decoder.cpp
@@ -27,7 +27,7 @@ private:
 
     Memory::MemorySystem& memory;
 
-    IMFTransform* transform = nullptr;
+    std::unique_ptr<IMFTransform, MFRelease<IMFTransform>> transform;
     DWORD in_stream_id = 0;
     DWORD out_stream_id = 0;
 };
@@ -70,13 +70,15 @@ std::optional<BinaryResponse> WMFDecoder::Impl::Initalize(const BinaryRequest& r
     }
 
     BinaryResponse response;
+    IMFTransform* tmp = nullptr;
     std::memcpy(&response, &request, sizeof(response));
     response.unknown1 = 0x0;
 
-    if (!MFDecoderInit(&transform)) {
+    if (!MFDecoderInit(&tmp)) {
         LOG_CRITICAL(Audio_DSP, "Can't init decoder");
         return response;
     }
+    transform.reset(tmp);
 
     HRESULT hr = transform->GetStreamIDs(1, &in_stream_id, 1, &out_stream_id);
     if (hr == E_NOTIMPL) {
@@ -85,7 +87,6 @@ std::optional<BinaryResponse> WMFDecoder::Impl::Initalize(const BinaryRequest& r
         out_stream_id = 0;
     } else if (FAILED(hr)) {
         ReportError("Decoder failed to initialize the stream ID", hr);
-        SafeRelease(&transform);
         return response;
     }
 
@@ -95,8 +96,8 @@ std::optional<BinaryResponse> WMFDecoder::Impl::Initalize(const BinaryRequest& r
 
 void WMFDecoder::Impl::Clear() {
     if (initalized) {
-        MFFlush(&transform);
-        MFDeInit(&transform);
+        MFFlush(transform.get());
+        MFDeInit(transform.get());
     }
     initalized = false;
     selected = false;
@@ -110,7 +111,7 @@ int WMFDecoder::Impl::DecodingLoop(ADTSData adts_header,
     IMFSample* output = nullptr;
 
     while (true) {
-        output_status = ReceiveSample(transform, out_stream_id, &output);
+        output_status = ReceiveSample(transform.get(), out_stream_id, &output);
 
         // 0 -> okay; 3 -> okay but more data available (buffer too small)
         if (output_status == OK || output_status == HAVE_MORE_DATA) {
@@ -192,9 +193,9 @@ std::optional<BinaryResponse> WMFDecoder::Impl::Decode(const BinaryRequest& requ
     if (!selected) {
         LOG_DEBUG(Audio_DSP, "New ADTS stream: channels = {}, sample rate = {}",
                   adts_header.channels, adts_header.samplerate);
-        SelectInputMediaType(transform, in_stream_id, adts_header, (UINT8*)aac_tag, 14);
-        SelectOutputMediaType(transform, out_stream_id);
-        SendSample(transform, in_stream_id, nullptr);
+        SelectInputMediaType(transform.get(), in_stream_id, adts_header, (UINT8*)aac_tag, 14);
+        SelectOutputMediaType(transform.get(), out_stream_id);
+        SendSample(transform.get(), in_stream_id, nullptr);
         // cache the result from detect_mediatype and call select_*_mediatype only once
         // This could increase performance very slightly
         transform->ProcessMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0);
@@ -205,7 +206,7 @@ std::optional<BinaryResponse> WMFDecoder::Impl::Decode(const BinaryRequest& requ
     sample->SetUINT32(MFSampleExtension_CleanPoint, 1);
 
     while (true) {
-        input_status = SendSample(transform, in_stream_id, sample);
+        input_status = SendSample(transform.get(), in_stream_id, sample);
 
         if (DecodingLoop(adts_header, out_streams) < 0) {
             // if the decode issues are caused by MFT not accepting new samples, try again
diff --git a/src/audio_core/hle/wmf_decoder_utils.cpp b/src/audio_core/hle/wmf_decoder_utils.cpp
index 459f5322c..8debac9d2 100644
--- a/src/audio_core/hle/wmf_decoder_utils.cpp
+++ b/src/audio_core/hle/wmf_decoder_utils.cpp
@@ -72,9 +72,8 @@ bool MFDecoderInit(IMFTransform** transform, GUID audio_format) {
     return true;
 }
 
-void MFDeInit(IMFTransform** transform) {
-    MFShutdownObject(*transform);
-    SafeRelease(transform);
+void MFDeInit(IMFTransform* transform) {
+    MFShutdownObject(transform);
     CoUninitialize();
 }
 
@@ -227,12 +226,12 @@ int DetectMediaType(char* buffer, size_t len, ADTSData* output, char** aac_tag)
     return 0;
 }
 
-void MFFlush(IMFTransform** transform) {
-    HRESULT hr = (*transform)->ProcessMessage(MFT_MESSAGE_COMMAND_FLUSH, 0);
+void MFFlush(IMFTransform* transform) {
+    HRESULT hr = (transform)->ProcessMessage(MFT_MESSAGE_COMMAND_FLUSH, 0);
     if (FAILED(hr)) {
         ReportError("MFT: Flush command failed", hr);
     }
-    hr = (*transform)->ProcessMessage(MFT_MESSAGE_NOTIFY_END_OF_STREAM, 0);
+    hr = (transform)->ProcessMessage(MFT_MESSAGE_NOTIFY_END_OF_STREAM, 0);
     if (FAILED(hr)) {
         ReportError("Failed to end streaming for MFT", hr);
     }
@@ -333,7 +332,8 @@ MFOutputState ReceiveSample(IMFTransform* transform, DWORD out_stream_id, IMFSam
 }
 
 int CopySampleToBuffer(IMFSample* sample, void** output, DWORD* len) {
-    IMFMediaBuffer* buffer;
+    std::unique_ptr<IMFMediaBuffer, MFRelease<IMFMediaBuffer>> buffer;
+    IMFMediaBuffer* tmp;
     HRESULT hr = S_OK;
     BYTE* data;
 
@@ -343,16 +343,16 @@ int CopySampleToBuffer(IMFSample* sample, void** output, DWORD* len) {
         return -1;
     }
 
-    sample->ConvertToContiguousBuffer(&buffer);
+    sample->ConvertToContiguousBuffer(&tmp);
     if (FAILED(hr)) {
         ReportError("Failed to get sample buffer", hr);
         return -1;
     }
+    buffer.reset(tmp);
 
     hr = buffer->Lock(&data, nullptr, nullptr);
     if (FAILED(hr)) {
         ReportError("Failed to lock the buffer", hr);
-        SafeRelease(&buffer);
         return -1;
     }
 
@@ -361,6 +361,5 @@ int CopySampleToBuffer(IMFSample* sample, void** output, DWORD* len) {
 
     // if buffer unlock fails, then... whatever, we have already got data
     buffer->Unlock();
-    SafeRelease(&buffer);
     return 0;
 }
diff --git a/src/audio_core/hle/wmf_decoder_utils.h b/src/audio_core/hle/wmf_decoder_utils.h
index 49b443fc2..0b27badcf 100644
--- a/src/audio_core/hle/wmf_decoder_utils.h
+++ b/src/audio_core/hle/wmf_decoder_utils.h
@@ -30,12 +30,19 @@ void SafeRelease(T** ppT) {
     }
 }
 
+template <class T>
+struct MFRelease {
+    void operator()(T* pointer) const {
+        pointer->Release();
+    };
+};
+
 void ReportError(std::string msg, HRESULT hr);
 
 // exported functions
 bool MFCoInit();
 bool MFDecoderInit(IMFTransform** transform, GUID audio_format = MFAudioFormat_AAC);
-void MFDeInit(IMFTransform** transform);
+void MFDeInit(IMFTransform* transform);
 IMFSample* CreateSample(void* data, DWORD len, DWORD alignment = 1, LONGLONG duration = 0);
 bool SelectInputMediaType(IMFTransform* transform, int in_stream_id, const ADTSData& adts,
                           UINT8* user_data, UINT32 user_data_len,
@@ -43,7 +50,7 @@ bool SelectInputMediaType(IMFTransform* transform, int in_stream_id, const ADTSD
 int DetectMediaType(char* buffer, size_t len, ADTSData* output, char** aac_tag);
 bool SelectOutputMediaType(IMFTransform* transform, int out_stream_id,
                            GUID audio_format = MFAudioFormat_PCM);
-void MFFlush(IMFTransform** transform);
+void MFFlush(IMFTransform* transform);
 int SendSample(IMFTransform* transform, DWORD in_stream_id, IMFSample* in_sample);
 MFOutputState ReceiveSample(IMFTransform* transform, DWORD out_stream_id, IMFSample** out_sample);
 int CopySampleToBuffer(IMFSample* sample, void** output, DWORD* len);