load_mp3.c
author Sam Lantinga <slouken@libsdl.org>
Wed, 17 Jun 2015 00:11:41 -0700
changeset 705 fe757163b8f7
parent 662 fd5af79fac03
child 711 f40c5ac95b12
permissions -rw-r--r--
Fixed bug 3018 - Loading MIDI music using FluidSynth leaks memory.

Philipp Wiesemann

There is a memory leak in fluidsynth.c and fluidsynth_loadsong_RW_internal(). The allocated temporary buffer is not deleted if fluid_player_add_mem() returns FLUID_OK.
slouken@662
     1
/*
slouken@662
     2
  SDL_mixer:  An audio mixer library based on the SDL library
slouken@662
     3
  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
slouken@662
     4
slouken@662
     5
  This software is provided 'as-is', without any express or implied
slouken@662
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@662
     7
  arising from the use of this software.
slouken@662
     8
slouken@662
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@662
    10
  including commercial applications, and to alter it and redistribute it
slouken@662
    11
  freely, subject to the following restrictions:
slouken@662
    12
slouken@662
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@662
    14
	 claim that you wrote the original software. If you use this software
slouken@662
    15
	 in a product, an acknowledgment in the product documentation would be
slouken@662
    16
	 appreciated but is not required.
slouken@662
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@662
    18
	 misrepresented as being the original software.
slouken@662
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@662
    20
slouken@662
    21
  This is the source needed to decode an MP3 into a waveform.
slouken@662
    22
*/
slouken@662
    23
slouken@662
    24
/* $Id$ */
slouken@662
    25
slouken@662
    26
#if defined(MP3_MUSIC) || defined(MP3_MAD_MUSIC)
slouken@662
    27
slouken@662
    28
#include "SDL_mixer.h"
slouken@662
    29
slouken@662
    30
#include "load_mp3.h"
slouken@662
    31
slouken@662
    32
#if defined(MP3_MUSIC)
slouken@662
    33
#include "dynamic_mp3.h"
slouken@662
    34
#elif defined(MP3_MAD_MUSIC)
slouken@662
    35
#include "music_mad.h"
slouken@662
    36
#endif
slouken@662
    37
slouken@662
    38
SDL_AudioSpec *Mix_LoadMP3_RW(SDL_RWops *src, int freesrc, SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len)
slouken@662
    39
{
slouken@662
    40
	/* note: spec is initialized to mixer spec */
slouken@662
    41
slouken@662
    42
#if defined(MP3_MUSIC)
slouken@662
    43
	SMPEG* mp3;
slouken@662
    44
	SMPEG_Info info;
slouken@662
    45
#elif defined(MP3_MAD_MUSIC)
slouken@662
    46
	mad_data *mp3_mad;
slouken@662
    47
#endif
slouken@662
    48
	long samplesize;
slouken@662
    49
	int read_len;
slouken@662
    50
	const Uint32 chunk_len = 4096;
slouken@662
    51
	int err = 0;
slouken@662
    52
slouken@662
    53
	if ((!src) || (!spec) || (!audio_buf) || (!audio_len))
slouken@662
    54
	{
slouken@662
    55
		return NULL;
slouken@662
    56
	}
slouken@662
    57
slouken@662
    58
	if (!err)
slouken@662
    59
	{
slouken@662
    60
		*audio_len = 0;
slouken@662
    61
		*audio_buf = (Uint8*) SDL_malloc(chunk_len);
slouken@662
    62
		err = (*audio_buf == NULL);
slouken@662
    63
	}
slouken@662
    64
slouken@662
    65
	if (!err)
slouken@662
    66
	{
slouken@662
    67
		err = ((Mix_Init(MIX_INIT_MP3) & MIX_INIT_MP3) == 0);
slouken@662
    68
	}
slouken@662
    69
slouken@662
    70
	if (!err)
slouken@662
    71
	{
slouken@662
    72
#if defined(MP3_MUSIC)
slouken@662
    73
		mp3 = smpeg.SMPEG_new_rwops(src, &info, freesrc, 0);
slouken@662
    74
		err = (mp3 == NULL);
slouken@662
    75
#elif defined(MP3_MAD_MUSIC)
slouken@662
    76
        mp3_mad = mad_openFileRW(src, spec, freesrc);
slouken@662
    77
		err = (mp3_mad == NULL);
slouken@662
    78
#endif
slouken@662
    79
	}
slouken@662
    80
slouken@662
    81
#if defined(MP3_MUSIC)
slouken@662
    82
	if (!err)
slouken@662
    83
	{
slouken@662
    84
		err = !info.has_audio;
slouken@662
    85
	}
slouken@662
    86
#endif
slouken@662
    87
slouken@662
    88
	if (!err)
slouken@662
    89
	{
slouken@662
    90
#if defined(MP3_MUSIC)
slouken@662
    91
slouken@662
    92
		smpeg.SMPEG_actualSpec(mp3, spec);
slouken@662
    93
slouken@662
    94
		smpeg.SMPEG_enableaudio(mp3, 1);
slouken@662
    95
		smpeg.SMPEG_enablevideo(mp3, 0);
slouken@662
    96
slouken@662
    97
		smpeg.SMPEG_play(mp3);
slouken@662
    98
slouken@662
    99
		/* read once for audio length */
slouken@662
   100
		while ((read_len = smpeg.SMPEG_playAudio(mp3, *audio_buf, chunk_len)) > 0)
slouken@662
   101
		{
slouken@662
   102
			*audio_len += read_len;
slouken@662
   103
		}
slouken@662
   104
slouken@662
   105
		smpeg.SMPEG_stop(mp3);
slouken@662
   106
slouken@662
   107
#elif defined(MP3_MAD_MUSIC)
slouken@662
   108
slouken@662
   109
        mad_start(mp3_mad);
slouken@662
   110
slouken@662
   111
		/* read once for audio length */
slouken@662
   112
		while ((read_len = mad_getSamples(mp3_mad, *audio_buf, chunk_len)) > 0)
slouken@662
   113
		{
slouken@662
   114
			*audio_len += read_len;
slouken@662
   115
		}
slouken@662
   116
slouken@662
   117
		mad_stop(mp3_mad);
slouken@662
   118
slouken@662
   119
#endif
slouken@662
   120
slouken@662
   121
		err = (read_len < 0);
slouken@662
   122
	}
slouken@662
   123
slouken@662
   124
	if (!err)
slouken@662
   125
	{
slouken@662
   126
		/* reallocate, if needed */
slouken@662
   127
		if ((*audio_len > 0) && (*audio_len != chunk_len))
slouken@662
   128
		{
slouken@662
   129
			*audio_buf = (Uint8*) SDL_realloc(*audio_buf, *audio_len);
slouken@662
   130
			err = (*audio_buf == NULL);
slouken@662
   131
		}
slouken@662
   132
	}
slouken@662
   133
slouken@662
   134
	if (!err)
slouken@662
   135
	{
slouken@662
   136
		/* read again for audio buffer, if needed */
slouken@662
   137
		if (*audio_len > chunk_len)
slouken@662
   138
		{
slouken@662
   139
#if defined(MP3_MUSIC)
slouken@662
   140
			smpeg.SMPEG_rewind(mp3);
slouken@662
   141
			smpeg.SMPEG_play(mp3);
slouken@662
   142
			err = (*audio_len != smpeg.SMPEG_playAudio(mp3, *audio_buf, *audio_len));
slouken@662
   143
			smpeg.SMPEG_stop(mp3);
slouken@662
   144
#elif defined(MP3_MAD_MUSIC)
slouken@662
   145
			mad_seek(mp3_mad, 0);
slouken@662
   146
			mad_start(mp3_mad);
slouken@662
   147
			err = (*audio_len != mad_getSamples(mp3_mad, *audio_buf, *audio_len));
slouken@662
   148
			mad_stop(mp3_mad);
slouken@662
   149
#endif
slouken@662
   150
		}
slouken@662
   151
	}
slouken@662
   152
slouken@662
   153
	if (!err)
slouken@662
   154
	{
slouken@662
   155
		/* Don't return a buffer that isn't a multiple of samplesize */
slouken@662
   156
		samplesize = ((spec->format & 0xFF)/8)*spec->channels;
slouken@662
   157
		*audio_len &= ~(samplesize-1);
slouken@662
   158
	}
slouken@662
   159
slouken@662
   160
#if defined(MP3_MUSIC)
slouken@662
   161
	if (mp3)
slouken@662
   162
	{
slouken@662
   163
		smpeg.SMPEG_delete(mp3); mp3 = NULL;
slouken@662
   164
		/* Deleting the MP3 closed the source if desired */
slouken@662
   165
		freesrc = SDL_FALSE;
slouken@662
   166
	}
slouken@662
   167
#elif defined(MP3_MAD_MUSIC)
slouken@662
   168
	if (mp3_mad)
slouken@662
   169
	{
slouken@662
   170
		mad_closeFile(mp3_mad); mp3_mad = NULL;
slouken@662
   171
		/* Deleting the MP3 closed the source if desired */
slouken@662
   172
		freesrc = SDL_FALSE;
slouken@662
   173
	}
slouken@662
   174
#endif
slouken@662
   175
slouken@662
   176
	if (freesrc)
slouken@662
   177
	{
slouken@662
   178
		SDL_RWclose(src); src = NULL;
slouken@662
   179
	}
slouken@662
   180
slouken@662
   181
	/* handle error */
slouken@662
   182
	if (err)
slouken@662
   183
	{
slouken@662
   184
		if (*audio_buf != NULL)
slouken@662
   185
		{
slouken@662
   186
			SDL_free(*audio_buf); *audio_buf = NULL;
slouken@662
   187
		}
slouken@662
   188
		*audio_len = 0;
slouken@662
   189
		spec = NULL;
slouken@662
   190
	}
slouken@662
   191
slouken@662
   192
	return spec;
slouken@662
   193
}
slouken@662
   194
slouken@662
   195
#endif