129 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			129 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|  | #include "soundstream.h"
 | ||
|  | 
 | ||
|  | #define STB_VORBIS_HEADER_ONLY
 | ||
|  | #include <kinc/libs/stb_vorbis.c>
 | ||
|  | 
 | ||
|  | #include <kinc/io/filereader.h>
 | ||
|  | 
 | ||
|  | #include <stdlib.h>
 | ||
|  | #include <string.h>
 | ||
|  | 
 | ||
|  | static kinc_a1_sound_stream_t streams[256]; | ||
|  | static int nextStream = 0; | ||
|  | static uint8_t buffer[1024 * 10]; | ||
|  | static int bufferIndex; | ||
|  | 
 | ||
|  | kinc_a1_sound_stream_t *kinc_a1_sound_stream_create(const char *filename, bool looping) { | ||
|  | 	kinc_a1_sound_stream_t *stream = &streams[nextStream]; | ||
|  | 	stream->myLooping = looping; | ||
|  | 	stream->myVolume = 1; | ||
|  | 	stream->rateDecodedHack = false; | ||
|  | 	stream->end = false; | ||
|  | 	kinc_file_reader_t file; | ||
|  | 	kinc_file_reader_open(&file, filename, KINC_FILE_TYPE_ASSET); | ||
|  | 	stream->buffer = &buffer[bufferIndex]; | ||
|  | 	bufferIndex += (int)kinc_file_reader_size(&file); | ||
|  | 	uint8_t *filecontent = (uint8_t *)malloc(kinc_file_reader_size(&file)); | ||
|  | 	kinc_file_reader_read(&file, filecontent, kinc_file_reader_size(&file)); | ||
|  | 	kinc_file_reader_close(&file); | ||
|  | 	memcpy(stream->buffer, filecontent, kinc_file_reader_size(&file)); | ||
|  | 	free(filecontent); | ||
|  | 	stream->vorbis = stb_vorbis_open_memory(buffer, (int)kinc_file_reader_size(&file), NULL, NULL); | ||
|  | 	if (stream->vorbis != NULL) { | ||
|  | 		stb_vorbis_info info = stb_vorbis_get_info(stream->vorbis); | ||
|  | 		stream->chans = info.channels; | ||
|  | 		stream->rate = info.sample_rate; | ||
|  | 	} | ||
|  | 	else { | ||
|  | 		stream->chans = 2; | ||
|  | 		stream->rate = 22050; | ||
|  | 	} | ||
|  | 	++nextStream; | ||
|  | 	return stream; | ||
|  | } | ||
|  | 
 | ||
|  | int kinc_a1_sound_stream_channels(kinc_a1_sound_stream_t *stream) { | ||
|  | 	return stream->chans; | ||
|  | } | ||
|  | 
 | ||
|  | int kinc_a1_sound_stream_sample_rate(kinc_a1_sound_stream_t *stream) { | ||
|  | 	return stream->rate; | ||
|  | } | ||
|  | 
 | ||
|  | bool kinc_a1_sound_stream_looping(kinc_a1_sound_stream_t *stream) { | ||
|  | 	return stream->myLooping; | ||
|  | } | ||
|  | 
 | ||
|  | void kinc_a1_sound_stream_set_looping(kinc_a1_sound_stream_t *stream, bool loop) { | ||
|  | 	stream->myLooping = loop; | ||
|  | } | ||
|  | 
 | ||
|  | float kinc_a1_sound_stream_volume(kinc_a1_sound_stream_t *stream) { | ||
|  | 	return stream->myVolume; | ||
|  | } | ||
|  | 
 | ||
|  | void kinc_a1_sound_stream_set_volume(kinc_a1_sound_stream_t *stream, float value) { | ||
|  | 	stream->myVolume = value; | ||
|  | } | ||
|  | 
 | ||
|  | bool kinc_a1_sound_stream_ended(kinc_a1_sound_stream_t *stream) { | ||
|  | 	return stream->end; | ||
|  | } | ||
|  | 
 | ||
|  | float kinc_a1_sound_stream_length(kinc_a1_sound_stream_t *stream) { | ||
|  | 	if (stream->vorbis == NULL) | ||
|  | 		return 0; | ||
|  | 	return stb_vorbis_stream_length_in_seconds(stream->vorbis); | ||
|  | } | ||
|  | 
 | ||
|  | float kinc_a1_sound_stream_position(kinc_a1_sound_stream_t *stream) { | ||
|  | 	if (stream->vorbis == NULL) | ||
|  | 		return 0; | ||
|  | 	return stb_vorbis_get_sample_offset(stream->vorbis) / stb_vorbis_stream_length_in_samples(stream->vorbis) * kinc_a1_sound_stream_length(stream); | ||
|  | } | ||
|  | 
 | ||
|  | void kinc_a1_sound_stream_reset(kinc_a1_sound_stream_t *stream) { | ||
|  | 	if (stream->vorbis != NULL) | ||
|  | 		stb_vorbis_seek_start(stream->vorbis); | ||
|  | 	stream->end = false; | ||
|  | 	stream->rateDecodedHack = false; | ||
|  | } | ||
|  | 
 | ||
|  | float *kinc_a1_sound_stream_next_frame(kinc_a1_sound_stream_t *stream) { | ||
|  | 	if (stream->vorbis == NULL) { | ||
|  | 		for (int i = 0; i < stream->chans; ++i) { | ||
|  | 			stream->samples[i] = 0; | ||
|  | 		} | ||
|  | 		return stream->samples; | ||
|  | 	} | ||
|  | 	if (stream->rate == 22050) { | ||
|  | 		if (stream->rateDecodedHack) { | ||
|  | 			stream->rateDecodedHack = false; | ||
|  | 			return stream->samples; | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | 	float left, right; | ||
|  | 	float *samples_array[2] = {&left, &right}; | ||
|  | 	int read = stb_vorbis_get_samples_float(stream->vorbis, stream->chans, samples_array, 1); | ||
|  | 	if (read == 0) { | ||
|  | 		if (kinc_a1_sound_stream_looping(stream)) { | ||
|  | 			stb_vorbis_seek_start(stream->vorbis); | ||
|  | 			stb_vorbis_get_samples_float(stream->vorbis, stream->chans, samples_array, 1); | ||
|  | 		} | ||
|  | 		else { | ||
|  | 			stream->end = true; | ||
|  | 			for (int i = 0; i < stream->chans; ++i) { | ||
|  | 				stream->samples[i] = 0; | ||
|  | 			} | ||
|  | 			return stream->samples; | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | 	stream->samples[0] = samples_array[0][0]; | ||
|  | 	stream->samples[1] = samples_array[1][0]; | ||
|  | 
 | ||
|  | 	stream->rateDecodedHack = true; | ||
|  | 	return stream->samples; | ||
|  | } |