Example #1
0
/**
 * Play a WAV file.
 * If the channel is playing, it's stopped before.
 * The file is automatically closed if no error is reported.
 * \param channel Channel to use.
 * \param file File to play.
 * \param loop If loop the playing.
 */
adv_error mixer_play_file_wav(unsigned channel, adv_fz* file, adv_bool loop)
{
	unsigned rate;
	unsigned bit;
	unsigned nchannel;
	unsigned size;

	mixer_channel_abort(channel);

	if (wave_read(file, &nchannel, &bit, &size, &rate) != 0) {
		return -1;
	}

	mixer_channel_alloc(channel, mixer_raw_file, loop);
	mixer_channel_set(channel, rate, nchannel, bit);

	mixer_map[channel].file = file;
	mixer_map[channel].start = fztell(file);
	mixer_map[channel].end = mixer_map[channel].start + size;
	mixer_map[channel].pos = mixer_map[channel].start;

	return 0;
}
Example #2
0
int wave_open(int id, int mode, void *args)
{
	struct wave_file *w = &wave[id];
    struct wave_args *wa = args;
	int result;

    /* wave already opened? */
	if( w->file )
		wave_close(id);

    w->file = wa->file;
	w->mode = mode;
	w->fill_wave = wa->fill_wave;
	w->smpfreq = wa->smpfreq;
	w->display = wa->display;

	if( w->mode )
	{
        w->resolution = 16;
		w->samples = w->smpfreq;
		w->length = w->samples * w->resolution / 8;
		w->data = malloc(w->length);
		if( !w->data )
		{
			logerror("WAVE malloc(%d) failed\n", w->length);
			memset(w, 0, sizeof(struct wave_file));
			return WAVE_ERR;
		}
		return INIT_OK;
    }
	else
	{
		result = wave_read(id);
		if( result == WAVE_OK )
		{
			/* return sample frequency in the user supplied structure */
			wa->smpfreq = w->smpfreq;
			w->offset = 0;
			return INIT_OK;
		}

		if( result == WAVE_FMT )
		{
			UINT8 *data;
			int bytes, pos, length;

			/* User supplied fill_wave function? */
			if( w->fill_wave == NULL )
			{
				logerror("WAVE no fill_wave callback, failing now\n");
				return WAVE_ERR;
			}

			logerror("WAVE creating wave using fill_wave() callback\n");

			/* sanity check: default chunk size is one byte */
			if( wa->chunk_size == 0 )
			{
				wa->chunk_size = 1;
				logerror("WAVE chunk_size defaults to %d\n", wa->chunk_size);
			}
			if( wa->smpfreq == 0 )
			{
				wa->smpfreq = 11025;
				logerror("WAVE smpfreq defaults to %d\n", w->smpfreq);
			}

			/* allocate a buffer for the binary data */
			data = malloc(wa->chunk_size);
			if( !data )
			{
				free(w->data);
				/* zap the wave structure */
				memset(&wave[id], 0, sizeof(struct wave_file));
				return WAVE_ERR;
			}

			/* determine number of samples */
			length =
				wa->header_samples +
				((osd_fsize(w->file) + wa->chunk_size - 1) / wa->chunk_size) * wa->chunk_samples +
				wa->trailer_samples;

			w->smpfreq = wa->smpfreq;
			w->resolution = 16;
			w->samples = length;
			w->length = length * 2;   /* 16 bits per sample */

			w->data = malloc(w->length);
			if( !w->data )
			{
				logerror("WAVE failed to malloc %d bytes\n", w->length);
				/* zap the wave structure */
				memset(&wave[id], 0, sizeof(struct wave_file));
				return WAVE_ERR;
			}
			logerror("WAVE creating max %d:%02d samples (%d) at %d Hz\n", (w->samples/w->smpfreq)/60, (w->samples/w->smpfreq)%60, w->samples, w->smpfreq);

			pos = 0;
			/* if there has to be a header */
			if( wa->header_samples > 0 )
			{
				length = (*w->fill_wave)((INT16 *)w->data + pos, w->samples - pos, CODE_HEADER);
				if( length < 0 )
				{
					logerror("WAVE conversion aborted at header\n");
					free(w->data);
					/* zap the wave structure */
					memset(&wave[id], 0, sizeof(struct wave_file));
					return WAVE_ERR;
				}
				logerror("WAVE header %d samples\n", length);
				pos += length;
			}

			/* convert the file data to samples */
			bytes = 0;
			osd_fseek(w->file, 0, SEEK_SET);
			while( pos < w->samples )
			{
				length = osd_fread(w->file, data, wa->chunk_size);
				if( length == 0 )
					break;
				bytes += length;
				length = (*w->fill_wave)((INT16 *)w->data + pos, w->samples - pos, data);
				if( length < 0 )
				{
					logerror("WAVE conversion aborted at %d bytes (%d samples)\n", bytes, pos);
					free(w->data);
					/* zap the wave structure */
					memset(&wave[id], 0, sizeof(struct wave_file));
					return WAVE_ERR;
				}
				pos += length;
			}
			logerror("WAVE converted %d data bytes to %d samples\n", bytes, pos);

			/* if there has to be a trailer */
			if( wa->trailer_samples )
			{
				if( pos < w->samples )
				{
					length = (*w->fill_wave)((INT16 *)w->data + pos, w->samples - pos, CODE_TRAILER);
					if( length < 0 )
					{
						logerror("WAVE conversion aborted at trailer\n");
						free(w->data);
						/* zap the wave structure */
						memset(&wave[id], 0, sizeof(struct wave_file));
						return WAVE_ERR;
					}
					logerror("WAVE trailer %d samples\n", length);
					pos += length;
				}
			}

			if( pos < w->samples )
			{
				/* what did the fill_wave() calls really fill into the buffer? */
				w->samples = pos;
				w->length = pos * 2;   /* 16 bits per sample */
				w->data = realloc(w->data, w->length);
				/* failure in the last step? how sad... */
				if( !w->data )
				{
					logerror("WAVE realloc(%d) failed\n", w->length);
					/* zap the wave structure */
					memset(&wave[id], 0, sizeof(struct wave_file));
					return WAVE_ERR;
				}
			}
			logerror("WAVE %d samples - %d:%02d\n", w->samples, (w->samples/w->smpfreq)/60, (w->samples/w->smpfreq)%60);
			/* hooray! :-) */
			return INIT_OK;
		}
	}
	return WAVE_ERR;
}