void test_push_mode_forever(FILE *g, char *filename) { int p,q, len, error, used; uint8 *data = stb_file(filename, &len); stb_vorbis *v; if (!data) stb_fatal("Couldn't open {%s}", filename); p = 0; q = 1; retry: v = stb_vorbis_open_pushdata(data, q, &used, &error, NULL); if (v == NULL) { if (error == VORBIS_need_more_data) { q += 1; goto retry; } printf("Error %d\n", error); exit(1); } p += used; show_info(v); for(;;) { int k=0; int n; float *left, *right; float **outputs; int num_c; q = 32; retry3: if (q > len-p) q = len-p; used = stb_vorbis_decode_frame_pushdata(v, data+p, q, &num_c, &outputs, &n); if (used == 0) { if (p+q == len) { // seek randomly when at end... this makes sense when listening to it, but dumb when writing to file p = stb_rand(); if (p < 0) p = -p; p %= (len - 8000); stb_vorbis_flush_pushdata(v); q = 128; goto retry3; } if (q < 128) q = 128; q *= 2; goto retry3; } p += used; if (n == 0) continue; left = outputs[0]; right = num_c > 1 ? outputs[1] : outputs[0]; write_floats(g, n, left, right); } stb_vorbis_close(v); }
void PCMAudioManager::fillStreamingBuffer(PCMStream *stream, U16 bufNum) { BOOL32 done = FALSE; U32 audioBufPos = 0; // char cBuf[50]; // sprintf(cBuf, "Filling bufNum %d", bufNum); // logmsg(cBuf); // U32 startingFilePos = stream->filePosition; while (!done) { // read data unsigned char buf[CHUNKED_READ_BUFFER_SIZE]; // sprintf(cBuf, "Reading at %d", stream->filePosition); // logmsg(cBuf); BOOL32 eof = FALSE; S32 bytesRead = _platform_read_asset_chunk(stream->assetName, stream->filePosition, buf, CHUNKED_READ_BUFFER_SIZE, &eof); if (bytesRead == 0) { // can't decode 0 bytes! The file must not be available. logmsg("Stream asset unavailable - stopping playback"); stream->isPlaying = FALSE; return; } if (stream->filePosition == 0) { // starting loop over, must flush or some audio files get stuck stb_vorbis_flush_pushdata((stb_vorbis*) stream->audioHandle); } S32 bytesConsumed = 0; // fill up audio buffer F32 **audioBuf; S32 samplesDecoded = 0; S32 channelsUsed = 0; BOOL32 hasMoreData = TRUE; S16 *streamAudioBuf = stream->audioBuf[bufNum]; while (hasMoreData && audioBufPos + (VORBIS_MAX_LEGAL_FRAME * stream->channels) < PCM_AUDIO_STREAM_BUFFER_SIZE) { S32 dBytesConsumed = stb_vorbis_decode_frame_pushdata((stb_vorbis*) stream->audioHandle, buf + bytesConsumed, bytesRead - bytesConsumed, &channelsUsed, &audioBuf, &samplesDecoded); if (dBytesConsumed < 0) { logmsg("vorbis decoder error"); hasMoreData = FALSE; } else if (dBytesConsumed == 0 && samplesDecoded == 0) { hasMoreData = FALSE; // logmsg("no bytes consumed or samples decoded"); } else if (samplesDecoded) { bytesConsumed += dBytesConsumed; // convert to interleaved short if (channelsUsed == 1) { // mono for (S32 i = 0; i < samplesDecoded; i++) { // quick convert to 32 bit sample, cap S32 sample = ((S32) ((audioBuf[0][i]) * (1 << (15)))); if ((unsigned int) (sample + 32768) > 65535) { sample = sample < 0 ? -32768 : 32767; } streamAudioBuf[audioBufPos + i] = sample; } } else if (channelsUsed == 2) { // stereo interleave for (S32 i = 0; i < samplesDecoded; i++) { S32 sample = ((S32) ((audioBuf[0][i]) * (1 << (15)))); if ((unsigned int) (sample + 32768) > 65535) { sample = sample < 0 ? -32768 : 32767; } streamAudioBuf[audioBufPos + (i*2)] = sample; sample = ((S32) ((audioBuf[1][i]) * (1 << (15)))); if ((unsigned int) (sample + 32768) > 65535) { sample = sample < 0 ? -32768 : 32767; } streamAudioBuf[audioBufPos + (i*2)+1] = sample; } } if (!stream->length) { stream->tempLength += samplesDecoded * channelsUsed; } audioBufPos += samplesDecoded * channelsUsed; } else { bytesConsumed += dBytesConsumed; } } stream->audioBufLimit[bufNum] = audioBufPos; if (eof) { stream->filePosition = 0; } else { stream->filePosition += bytesConsumed; stream->filePosition %= stream->assetLength; } stream->audioBufEmpty[bufNum] = FALSE; if (hasMoreData) { // buffer is full done = TRUE; // TODO - oops, what was this supposed to do? //if (stream->filePosition < 0) { // stream->filePosition = startingFilePos + bytesConsumed; //} } } }