Sound::Sound(const std::string& fileName) : _channel_count(0), _sample_count(0), _sample_rate(0) { stb_vorbis* file = stb_vorbis_open_filename(const_cast<char*>(fileName.c_str()), 0, 0); if (file) { stb_vorbis_info info = stb_vorbis_get_info(file); _channel_count = info.channels; _sample_rate = info.sample_rate; int samples = stb_vorbis_stream_length_in_samples(file) * _channel_count; _sample_count = samples; _samples.resize(samples); stb_vorbis_get_samples_short_interleaved(file, _channel_count, &_samples.front(), samples); stb_vorbis_close(file); } else { throw std::runtime_error("Unable to open audio file"); } }
static void punp_sound_load_stbv(Sound *sound, stb_vorbis *stream) { stb_vorbis_info info = stb_vorbis_get_info(stream); sound->volume = PUNP_SOUND_DEFAULT_SOUND_VOLUME; sound->rate = info.sample_rate; sound->samples_count = stb_vorbis_stream_length_in_samples(stream); sound->samples = (i16 *)bank_push(CORE->storage, PUNP_SOUND_SAMPLES_TO_BYTES(sound->samples_count)); { static i16 buffer[1024]; i16 *it = sound->samples; int samples_read_per_channel; for (; ;) { int samples_read_per_channel = stb_vorbis_get_samples_short_interleaved(stream, PUNP_SOUND_CHANNELS, buffer, 1024); if (samples_read_per_channel == 0) { break; } // 2 channels, 16 bits per sample. memcpy(it, buffer, PUNP_SOUND_SAMPLES_TO_BYTES(samples_read_per_channel)); it += samples_read_per_channel * PUNP_SOUND_CHANNELS; } } stb_vorbis_close(stream); }
//---------------------------------------------------------------------------- void fill_buffer(void *audioBuffer, size_t size) { //---------------------------------------------------------------------------- u32 *dest = (u32*)audioBuffer; stb_vorbis_get_samples_short_interleaved(vorbisFile, 2, (short*)dest, Samples * 2); DSP_FlushDataCache(audioBuffer,size); }
std::size_t cSoundFileOgg::Read( Int16 * Data, std::size_t SamplesCount ) { if ( NULL != mStream && Data && SamplesCount ) { int Read = stb_vorbis_get_samples_short_interleaved( mStream, mChannelCount, Data, static_cast<int>( SamplesCount ) ); std::size_t scount = Read * mChannelCount; return scount; } return 0; }
int MusicPlayer::pullAudio(AUDIO_SAMPLE_TYPE *target, int sampleCount) { memset(target, 0, sampleCount * sizeof(AUDIO_SAMPLE_TYPE)); #ifdef USE_OGG if(v && error==0) { int samples = stb_vorbis_get_samples_short_interleaved(v, channels, target, sampleCount); if(samples==0) { stb_vorbis_seek_start(v); stb_vorbis_get_samples_short_interleaved(v, channels, target, sampleCount); // error=-1; } } #endif #ifdef USE_MP3 if (!error) { size_t done; error = mpg123_read(mh, (unsigned char *) target, sampleCount * sizeof(AUDIO_SAMPLE_TYPE), &done); // read will return MPG123_DONE eventually... if (error == MPG123_DONE) { mpg123_seek(mh, 0, SEEK_SET); error = mpg123_read(mh, (unsigned char *) target, sampleCount * sizeof(AUDIO_SAMPLE_TYPE), &done); } // ignore format change if (error == MPG123_NEW_FORMAT) error = MPG123_OK; } #endif return sampleCount; }
// Load OGG file into Wave structure // NOTE: Using stb_vorbis library static Wave LoadOGG(char *fileName) { Wave wave; stb_vorbis *oggFile = stb_vorbis_open_filename(fileName, NULL, NULL); if (oggFile == NULL) { TraceLog(WARNING, "[%s] OGG file could not be opened", fileName); wave.data = NULL; } else { stb_vorbis_info info = stb_vorbis_get_info(oggFile); wave.sampleRate = info.sample_rate; wave.bitsPerSample = 16; wave.channels = info.channels; TraceLog(DEBUG, "[%s] Ogg sample rate: %i", fileName, info.sample_rate); TraceLog(DEBUG, "[%s] Ogg channels: %i", fileName, info.channels); int totalSamplesLength = (stb_vorbis_stream_length_in_samples(oggFile) * info.channels); wave.dataSize = totalSamplesLength*sizeof(short); // Size must be in bytes TraceLog(DEBUG, "[%s] Samples length: %i", fileName, totalSamplesLength); float totalSeconds = stb_vorbis_stream_length_in_seconds(oggFile); TraceLog(DEBUG, "[%s] Total seconds: %f", fileName, totalSeconds); if (totalSeconds > 10) TraceLog(WARNING, "[%s] Ogg audio lenght is larger than 10 seconds (%f), that's a big file in memory, consider music streaming", fileName, totalSeconds); int totalSamples = totalSeconds*info.sample_rate*info.channels; TraceLog(DEBUG, "[%s] Total samples calculated: %i", fileName, totalSamples); wave.data = malloc(sizeof(short)*totalSamplesLength); int samplesObtained = stb_vorbis_get_samples_short_interleaved(oggFile, info.channels, wave.data, totalSamplesLength); TraceLog(DEBUG, "[%s] Samples obtained: %i", fileName, samplesObtained); TraceLog(INFO, "[%s] OGG file loaded successfully (SampleRate: %i, BitRate: %i, Channels: %i)", fileName, wave.sampleRate, wave.bitsPerSample, wave.channels); stb_vorbis_close(oggFile); } return wave; }
void test_get_samples_short_interleaved(FILE *g, char *filename) { int error; stb_vorbis *v = stb_vorbis_open_filename(filename, &error, NULL); if (!v) stb_fatal("Couldn't open {%s}", filename); show_info(v); for(;;) { int16 sbuffer[333]; int n; n = stb_vorbis_get_samples_short_interleaved(v, 2, sbuffer, 333); if (n == 0) break; fwrite(sbuffer, 2, n*2, g); } stb_vorbis_close(v); }
int try_seeking(stb_vorbis *v, unsigned int pos, short *output, unsigned int num_samples) { int count; short samples[SAMPLES_TO_TEST*2]; assert(pos <= num_samples); if (!stb_vorbis_seek(v, pos)) { fprintf(stderr, "Seek to %u returned error from stb_vorbis\n", pos); return 0; } count = stb_vorbis_get_samples_short_interleaved(v, 2, samples, SAMPLES_TO_TEST*2); if (count > (int) (num_samples - pos)) { fprintf(stderr, "Seek to %u allowed decoding %d samples when only %d should have been valid.\n", pos, count, (int) (num_samples - pos)); return 0; } if (count < SAMPLES_TO_TEST && count < (int) (num_samples - pos)) { fprintf(stderr, "Seek to %u only decoded %d samples of %d attempted when at least %d should have been valid.\n", pos, count, SAMPLES_TO_TEST, num_samples - pos); return 0; } if (0 != memcmp(samples, output + pos*2, count*2)) { int k; for (k=0; k < SAMPLES_TO_TEST*2; ++k) { if (samples[k] != output[k]) { fprintf(stderr, "Seek to %u produced incorrect samples starting at sample %u (short #%d in buffer).\n", pos, pos + (k/2), k); break; } } assert(k != SAMPLES_TO_TEST*2); return 0; } return 1; }
ALuint AEAudioContextBufferLoad(AEAudioContext* self, const char* filename){ ALuint buffer=0; alGenBuffers(1, &buffer); stb_vorbis *stream = stb_vorbis_open_filename((char*)filename, NULL, NULL); if(not stream) return 0; stb_vorbis_info info = stb_vorbis_get_info(stream); ALenum format; if(info.channels == 2) format = AL_FORMAT_STEREO16; else format = AL_FORMAT_MONO16; size_t sampleCount = stb_vorbis_stream_length_in_samples(stream) * info.channels; void* data = malloc(sizeof(ALushort)*sampleCount); stb_vorbis_get_samples_short_interleaved(stream, info.channels, data, (int)sampleCount); stb_vorbis_close(stream); alBufferData(buffer, format, data, sampleCount * sizeof(ALushort), info.sample_rate); free(data); return buffer; }
bool AudioStream::Stream(unsigned int buffer) { ALenum format; if (info.channels == 1) { format = AL_FORMAT_MONO16; } else { format = AL_FORMAT_STEREO16; } int16 pcm[32768]; int size = stb_vorbis_get_samples_short_interleaved(stream, info.channels, pcm, 32768); if (!size) { return false; } else { alBufferData(buffer, format, pcm, size * info.channels * sizeof(short), info.sample_rate); samplesLeft -= size; return true; } }
// Fill music buffers with new data from music stream static bool BufferMusicStream(ALuint buffer) { short pcm[MUSIC_BUFFER_SIZE]; int size = 0; // Total size of data steamed (in bytes) int streamedBytes = 0; // Bytes of data obtained in one samples get bool active = true; // We can get more data from stream (not finished) if (musicEnabled) { while (size < MUSIC_BUFFER_SIZE) { streamedBytes = stb_vorbis_get_samples_short_interleaved(currentMusic.stream, currentMusic.channels, pcm + size, MUSIC_BUFFER_SIZE - size); if (streamedBytes > 0) size += (streamedBytes*currentMusic.channels); else break; } TraceLog(DEBUG, "Streaming music data to buffer. Bytes streamed: %i", size); } if (size > 0) { alBufferData(buffer, currentMusic.format, pcm, size*sizeof(short), currentMusic.sampleRate); currentMusic.totalSamplesLeft -= size; } else { active = false; TraceLog(WARNING, "No more data obtained from stream"); } return active; }
bool AEAudioStreamStream(AEAudioStream* self, ALuint buffer){ //Uncomment this to avoid VLAs //#define BUFFER_SIZE 4096*32 #ifndef BUFFER_SIZE//VLAs ftw #define BUFFER_SIZE (self->bufferSize) #endif ALshort pcm[BUFFER_SIZE]; int size = 0; int result = 0; while(size < BUFFER_SIZE){ result = stb_vorbis_get_samples_short_interleaved(self->stream, self->info.channels, pcm+size, BUFFER_SIZE-size); if(result > 0) size += result*self->info.channels; else break; } if(size == 0) return false; alBufferData(buffer, self->format, pcm, size*sizeof(ALshort), self->info.sample_rate); self->totalSamplesLeft-=size; #undef BUFFER_SIZE return true; }
// stereo LRLRLR order void mixerCallback( void* userdata, Uint8* streamData, int len ) { memset( streamData, len, workingSilence ); memset( workingBuffer, 0, workingBufferSize ); if( workingBuffer == NULL ) { return; } int numSamples = ( len / WORKING_CHANNELS ) / ( ( SDL_AUDIO_MASK_BITSIZE & WORKING_FORMAT ) / 8 ); #if 0 int soundFreq = 440; // wave length float step = 1.0f / WORKING_RATE; // for testing audio output for( int s = 0; s < numSamples; ++s ) { int streamIdx = ( s * WORKING_CHANNELS ); testTimePassed += 1.0f / WORKING_RATE; float v = sinf( testTimePassed * soundFreq * M_TWO_PI_F ); workingBuffer[streamIdx] = v * 0.1f; workingBuffer[streamIdx+1] = v * 0.1f; } #else // advance each playing sound for( EntityID id = idSet_GetFirstValidID( &playingIDSet ); id != INVALID_ENTITY_ID; id = idSet_GetNextValidID( &playingIDSet, id ) ) { int i = idSet_GetIndex( id ); Sound* snd = &( playingSounds[i] ); Sample* sample = &( samples[snd->sample] ); // for right now lets assume the pitch will stay the same, when we get it working it'll just involve // changing the speed at which we move through the array bool soundDone = false; float volume = snd->volume * sbSoundGroups[snd->group].volume * masterVolume; for( int s = 0; ( s < numSamples ) && !soundDone; ++s ) { int streamIdx = ( s * WORKING_CHANNELS ); // we're assuming stereo output here if( sample->numChannels == 1 ) { float data = sample->data[(int)snd->pos] * volume; /* left */ workingBuffer[streamIdx] += data * inverseLerp( 1.0f, 0.0f, snd->pan ); /* right */ workingBuffer[streamIdx+1] += data * inverseLerp( -1.0f, 0.0f, snd->pan ); snd->pos += snd->pitch; } else { // if the sample is stereo then we ignore panning // NOTE: Pitch change doesn't work with stereo samples yet workingBuffer[streamIdx] += sample->data[(int)snd->pos] * volume; workingBuffer[streamIdx+1] += sample->data[(int)snd->pos+1] * volume; snd->pos += 2.0f; } if( snd->pos >= sample->numSamples ) { if( sample->loops ) { snd->pos -= (float)sample->numSamples; } else { soundDone = true; } } } if( soundDone ) { idSet_ReleaseID( &playingIDSet, id ); // this doesn't invalidate the id for the loop } } for( int i = 0; i < MAX_STREAMING_SOUNDS; ++i ) { if( !streamingSounds[i].playing ) continue; StreamingSound* stream = &( streamingSounds[i] ); bool soundDone = false; float volume = stream->volume * sbSoundGroups[stream->group].volume * masterVolume; // if the next buffer fill would be past what we have loaded then load some more // note: the SDL_AudioStreamAvailable return value is in bytes while( ( SDL_AudioStreamAvailable( stream->sdlStream ) < len ) && !( stream->readDone ) ) { int read = 0; int request = STREAM_READ_BUFFER_SIZE / sizeof( short ); size_t test = ARRAY_SIZE( streamReadBuffer ); // returns the number of samples stored per channel int samplesPerChannel = stb_vorbis_get_samples_short_interleaved( stream->access, stream->access->channels, streamReadBuffer, request ); read = samplesPerChannel * sizeof( short ); SDL_AudioStreamPut( stream->sdlStream, streamReadBuffer, samplesPerChannel * stream->channels * sizeof( short ) ); // reached the end of the file, are we looping? if( read != request ) { if( stream->loops ) { stb_vorbis_seek_start( stream->access ); } else { stream->readDone = true; SDL_AudioStreamFlush( stream->sdlStream ); } } } // read data from the audio stream until there is no more left or the end of the buffer to fill int bytesToStream = numSamples * stream->channels * sizeof( sbStreamWorkingBuffer[0] ); sb_Reserve( sbStreamWorkingBuffer, (size_t)bytesToStream ); int gotten = SDL_AudioStreamGet( stream->sdlStream, sbStreamWorkingBuffer, bytesToStream ); if( gotten < 0 ) { llog( LOG_ERROR, "Error reading from sdlStream: %s", SDL_GetError( ) ); stream->playing = false; continue; } else if( gotten == 0 ) { // end of stream stream->playing = false; } int samplesGotten = gotten / ( stream->channels * sizeof( sbStreamWorkingBuffer[0] ) ); for( int s = 0; s < samplesGotten; ++s ) { // then just mix those samples int streamIdx = ( s * WORKING_CHANNELS ); int workingIdx = ( s * stream->channels ); // we're assuming stereo output here if( stream->access->channels == 1 ) { float data = sbStreamWorkingBuffer[workingIdx] * volume; workingBuffer[streamIdx] += data * inverseLerp( 1.0f, 0.0f, stream->pan ); // left workingBuffer[streamIdx+1] += data * inverseLerp( -1.0f, 0.0f, stream->pan ); // right } else { // if the sample is stereo then we ignore panning workingBuffer[streamIdx] += sbStreamWorkingBuffer[workingIdx] * volume; workingBuffer[streamIdx+1] += sbStreamWorkingBuffer[workingIdx + 1] * volume; } } } #endif memcpy( streamData, workingBuffer, len ); }
SGAudioBuffer* SG_CALL sgAudioBufferCreateStream(SGStream* stream, SGbool delstream) { if(!stream || !stream->read || !stream->seek || !stream->tell) return NULL; SGAudioBuffer* buffer = malloc(sizeof(SGAudioBuffer)); if(!buffer) goto error; buffer->stream = stream; buffer->del = delstream; buffer->handle = malloc(sizeof(ALuint)); if(!buffer->handle) goto error; alGenBuffers(1, buffer->handle); SGuint channels; SGuint format; SGuint frequency; void* data = NULL; SGuint datalen; SGuint nsamples; void* buf = NULL; int error = 0; stb_vorbis* stb = NULL; stb_vorbis_info info; SGlong pos = sgStreamTell(stream); SGlong size = sgStreamTellSize(stream); size -= pos; if(pos < 0 || size < 0) goto lderr; buf = malloc(size); if(sgStreamRead(stream, buf, 1, size) != size) goto lderr; stb = stb_vorbis_open_memory(buf, size, &error, NULL); if(!stb) goto lderr; info = stb_vorbis_get_info(stb); channels = info.channels; frequency = info.sample_rate; format = SG_AUDIO_FORMAT_S16; // or SG_AUDIO_FORMAT_F nsamples = stb_vorbis_stream_length_in_samples(stb); datalen = 2 * nsamples * channels; data = malloc(datalen); datalen = 2 * stb_vorbis_get_samples_short_interleaved(stb, info.channels, data, datalen / 2); sgAudioBufferSetData(buffer, channels, format, frequency, data, datalen); free(data); end: if(stb) stb_vorbis_close(stb); if(buf) free(buf); return buffer; lderr: if(buffer) { free(buffer); buffer = NULL; goto end; } error: if(buffer) free(buffer); return NULL; }
quint64 nVorbisStream::read(void *data, unsigned long frames) { return stb_vorbis_get_samples_short_interleaved(_vorbis, _channels, (short*) data, frames * _channels ); }
AudioBuffer::AudioBuffer(const String &filename) { if (filename.ExtractExt() == "wav") { m_alBuffer = 0; File * file = new File(filename, FILE_READ); int32 chunkId = file->ReadInt(); int32 riffChunkSize = file->ReadInt(); int32 format = file->ReadInt(); int32 subChunkId = file->ReadInt(); int32 fmtChunkSize = file->ReadInt(); int16 audioFormat = file->ReadInt16(); int16 channels = file->ReadInt16(); int32 sampleRate = file->ReadInt(); int32 byteRate = file->ReadInt(); int16 blockAlign = file->ReadInt16(); int16 bitsPerSample = file->ReadInt16(); if (fmtChunkSize > 16) { int16 extraParamsSize = file->ReadInt16(); file->Seek(file->Pos() + extraParamsSize); } char text[5] = ""; file->ReadBytes(text, 4); while (String(text) != "data" && !file->Eof()) { file->ReadBytes(text, 4); if (String(text) == "data") break; file->Seek(file->Pos() + 4); } int32 dataSize = file->ReadInt(); uint32 * data = (uint32 *)malloc(dataSize); file->ReadBytes(data, dataSize); ALenum bufferFormat; if (bitsPerSample == 8) { if (channels == 1) bufferFormat = AL_FORMAT_MONO8; else bufferFormat = AL_FORMAT_STEREO8; } else { if (channels == 1) bufferFormat = AL_FORMAT_MONO16; else bufferFormat = AL_FORMAT_STEREO16; } alGenBuffers(1, &m_alBuffer); alBufferData(m_alBuffer, bufferFormat, data, dataSize, sampleRate); delete file; free(data); } else if (filename.ExtractExt() == "ogg") { stb_vorbis * file = stb_vorbis_open_filename(filename.ToCString(), nullptr, nullptr); if (file) { stb_vorbis_info info = stb_vorbis_get_info(file); uint32 size = stb_vorbis_stream_length_in_samples(file) * info.channels; int16 * buffer = (int16 *)malloc(size * sizeof(int16)); stb_vorbis_get_samples_short_interleaved(file, info.channels, buffer, size); alGenBuffers(1, &m_alBuffer); ALenum bufferFormat; if (info.channels == 1) bufferFormat = AL_FORMAT_MONO16; else bufferFormat = AL_FORMAT_STEREO16; alBufferData(m_alBuffer, bufferFormat, buffer, size, info.sample_rate); stb_vorbis_close(file); free(buffer); } } }
const i32 audio_updateAndPlay(MemoryArena_ *arena, AudioManager *audioManager, AudioRenderer *audioRenderer) { AudioVorbis *audio = audioRenderer->audio; if (!audio) return 0; u32 alSourceId = getSourceId(audioManager, audioRenderer); if (alIsSource(alSourceId) == AL_FALSE) { DEBUG_LOG("audio_updateAndPlay(): Update failed on invalid source id"); return -1; } ALint audioState; alGetSourcei(alSourceId, AL_SOURCE_STATE, &audioState); AL_CHECK_ERROR(); if (audioState == AL_STOPPED || audioState == AL_INITIAL) { if (audioState == AL_STOPPED) { if (audioRenderer->numPlays != AUDIO_REPEAT_INFINITE) audioRenderer->numPlays--; if (audioRenderer->numPlays == AUDIO_REPEAT_INFINITE || audioRenderer->numPlays > 0) { // TODO(doyle): Delete and recreate fixes clicking when reusing // buffers alDeleteBuffers(ARRAY_COUNT(audioRenderer->bufferId), audioRenderer->bufferId); AL_CHECK_ERROR(); alGenBuffers(ARRAY_COUNT(audioRenderer->bufferId), audioRenderer->bufferId); AL_CHECK_ERROR(); } else { i32 result = rendererRelease(arena, audioManager, audioRenderer); return result; } } if (audioRenderer->isStreaming) { stb_vorbis_seek_start(audio->file); for (i32 i = 0; i < ARRAY_COUNT(audioRenderer->bufferId); i++) { i16 audioChunk[AUDIO_CHUNK_SIZE_] = {0}; stb_vorbis_get_samples_short_interleaved( audio->file, audio->info.channels, audioChunk, AUDIO_CHUNK_SIZE_); alBufferData(audioRenderer->bufferId[i], audioRenderer->format, audioChunk, AUDIO_CHUNK_SIZE_ * sizeof(i16), audio->info.sample_rate); AL_CHECK_ERROR(); } alSourceQueueBuffers(alSourceId, ARRAY_COUNT(audioRenderer->bufferId), audioRenderer->bufferId); } else { alSourceQueueBuffers(alSourceId, 1, audioRenderer->bufferId); } AL_CHECK_ERROR(); alSourcePlay(alSourceId); AL_CHECK_ERROR(); } else if (audioState == AL_PLAYING) { ALint numProcessedBuffers; alGetSourcei(alSourceId, AL_BUFFERS_PROCESSED, &numProcessedBuffers); AL_CHECK_ERROR(); if (numProcessedBuffers > 0) { // TODO(doyle): Possibly wrong, we should pass in all processed buffers? ALint numBuffersToUnqueue = 1; ALuint emptyBufferId; alSourceUnqueueBuffers(alSourceId, numBuffersToUnqueue, &emptyBufferId); AL_CHECK_ERROR(); i16 audioChunk[AUDIO_CHUNK_SIZE_] = {0}; i32 sampleCount = stb_vorbis_get_samples_short_interleaved( audio->file, audio->info.channels, audioChunk, AUDIO_CHUNK_SIZE_); /* There are still samples to play */ if (sampleCount > 0) { alBufferData(emptyBufferId, audioRenderer->format, audioChunk, sampleCount * audio->info.channels * sizeof(i16), audio->info.sample_rate); AL_CHECK_ERROR(); alSourceQueueBuffers(alSourceId, 1, &emptyBufferId); AL_CHECK_ERROR(); } } } return 0; }
AudioBuffer::AudioBuffer(const String & filename):alBuffer(0) { if (filename.ExtractExt() == "wav") { alGenBuffers(1, &alBuffer); File file(filename, FILE_READ); file.Seek(16); uint32 fmtChunkSize; file.ReadBytes(&fmtChunkSize, 4); uint16 audioFormat; file.ReadBytes(&audioFormat, 2); uint16 channels; file.ReadBytes(&channels, 2); file.Seek(24); uint32 sampleRate; file.ReadBytes(&sampleRate, 4); file.Seek(34); uint16 bitsPerSample; file.ReadBytes(&bitsPerSample, 2); uint16 extraParamSize; if (fmtChunkSize != 16) { file.ReadBytes(&extraParamSize, 2); file.Seek(38 + extraParamSize); } char texto[5]; texto[4] = '\0'; while (String(texto) != "data") { file.ReadBytes(texto, 4); } uint32 dataSize; uint32* data; file.ReadBytes(&dataSize, 4); data = (uint32*)malloc(dataSize); file.ReadBytes(data, dataSize); ALenum format; if (bitsPerSample == 8) { if (channels == 1) { format = AL_FORMAT_MONO8; } else { format = AL_FORMAT_STEREO8; } } if (bitsPerSample == 16) { if (channels == 1) { format = AL_FORMAT_MONO16; } else { format = AL_FORMAT_STEREO16; } } alBufferData(alBuffer, format, data, dataSize, sampleRate); free(data); } else if (filename.ExtractExt() == "ogg") { stb_vorbis* stb_vorbis; stb_vorbis = stb_vorbis_open_filename(filename.ToCString(), nullptr, nullptr); if (stb_vorbis == nullptr) return; stb_vorbis_info info = stb_vorbis_get_info(stb_vorbis); uint32 dataSize = stb_vorbis_stream_length_in_samples(stb_vorbis) * info.channels; int16* buffer = (int16*)malloc(dataSize * sizeof(uint16)); stb_vorbis_get_samples_short_interleaved(stb_vorbis, info.channels,(short *) buffer, dataSize); alGenBuffers(1, &alBuffer); ALenum format; if (info.channels == 1) { format = AL_FORMAT_MONO16; } else { format = AL_FORMAT_STEREO16; } alBufferData(alBuffer, format, buffer, dataSize * sizeof(int16), info.sample_rate); free(buffer); stb_vorbis_close(stb_vorbis); } }
sInt sOGGDecoder::Render(sS16 *stream,sInt samples) { return stb_vorbis_get_samples_short_interleaved(dec,2,stream,samples*2); }
int main() { // Initialize services srvInit(); aptInit(); hidInit(NULL); ptmInit(); gfxInitDefault(); // consoleInit(GFX_TOP, NULL); csndInit(); // fsInit(); // sdmcInit(); chdir("sdmc:/"); void *device = gfxCreateDevice(240, 320); gfxMakeCurrent(device); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0.0, 1.0, 1.0, 0.0, -1.0, 1.0); glTranslatef(0.5f, 0.5f, 0.0f); glRotatef(90.0f, 0.0f, 0.0f, 1.0f); glTranslatef(-0.5f, -0.5f, 0.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glGenTextures(1, &play_button); glGenTextures(1, &pause_button); glGenTextures(1, &loop_button); glGenTextures(1, &loop_disable_button); glGenTextures(1, &power_icon); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); int x, y, n; u8* image_data = stbi_load_from_memory(play_3_png, play_3_png_size, &x, &y, &n, 4); glBindTexture(GL_TEXTURE_2D, play_button); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data); stbi_image_free(image_data); image_data = stbi_load_from_memory(pause_2_png, pause_2_png_size, &x, &y, &n, 4); glBindTexture(GL_TEXTURE_2D, pause_button); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data); stbi_image_free(image_data); image_data = stbi_load_from_memory(loop_png, loop_png_size, &x, &y, &n, 4); glBindTexture(GL_TEXTURE_2D, loop_button); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data); stbi_image_free(image_data); image_data = stbi_load_from_memory(loop_disable_png, loop_disable_png_size, &x, &y, &n, 4); glBindTexture(GL_TEXTURE_2D, loop_disable_button); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data); stbi_image_free(image_data); image_data = stbi_load_from_memory(power_png, power_png_size, &x, &y, &n, 4); glBindTexture(GL_TEXTURE_2D, power_icon); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data); stbi_image_free(image_data); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); void *top_device = gfxCreateDevice(240, 400); gfxMakeCurrent(top_device); initfont_goth(); initfont_anita(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0.0, 1.0, 1.0, 0.0, -1.0, 1.0); glTranslatef(0.5f, 0.5f, 0.0f); glRotatef(90.0f, 0.0f, 0.0f, 1.0f); glTranslatef(-0.5f, -0.5f, 0.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); glEnable(GL_TEXTURE_2D); int frames = 0; int channel = 0x8; while (aptMainLoop()) { gspWaitForVBlank(); hidScanInput(); gfxMakeCurrent(top_device); glClear(GL_COLOR_BUFFER_BIT); glLoadIdentity(); glScalef(1.0/400.0, 1.0/240.0, 1.0); state_man(); gfxFlush(gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL)); u8 plevel; u8 charge; PTMU_GetBatteryLevel(NULL, &plevel); PTMU_GetBatteryChargeState(NULL, &charge); if (plevel != power_level) { power_level = plevel; // draw_ui = true; } if (charge != is_charging) { is_charging = charge; //draw_ui = true; } gfxMakeCurrent(device); u8* fb = gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL); render(); gfxFlush(fb); // Your code goes here u32 kDown = hidKeysDown(); if (kDown & KEY_START) break; // break in order to return to hbmenu // Flush and swap framebuffers if (audiobuf && !paused) { if(frames >= 50) { frames = 0; int n = 0; if (decode_mode == AUDIO_MODE_VORBIS) { n = stb_vorbis_get_samples_short_interleaved(v, 2, audiobuf, Samples * 2); } else { while (audiobuf_index < Samples * 2) { n = FLAC__stream_decoder_process_single(FLAC_decoder); if (FLAC__stream_decoder_get_state(FLAC_decoder) == FLAC__STREAM_DECODER_END_OF_STREAM) break; } audiobuf_index = 0; } if(n == 0) { if (decode_mode == AUDIO_MODE_VORBIS) { stb_vorbis_close(v); } else { FLAC__stream_decoder_delete(FLAC_decoder); } linearFree(audiobuf); audiobuf = NULL; v = NULL; FLAC_decoder = NULL; if (loop_flag) play_file_from_filename(currently_playing); } GSPGPU_FlushDataCache(NULL, (u8*)audiobuf, audiobuf_size); if (channel == 0x8) channel = 0x6; if (channel == 0x6) channel = 0x8; csndPlaySound(SOUND_CHANNEL(channel), SOUND_ONE_SHOT | SOUND_LINEAR_INTERP | SOUND_FORMAT_16BIT, Samples * 2, 10.0, 0.0, (u32*)audiobuf, (u32*)audiobuf, audiobuf_size); } frames++; } gfxFlushBuffers(); gfxSwapBuffersGpu(); } // Exit services if (FLAC_decoder) { FLAC__stream_decoder_delete(FLAC_decoder); } csndExit(); gfxExit(); ptmExit(); hidExit(); aptExit(); srvExit(); return 0; }