void LoadTestChannel(ShadertoyTestResource *channel_data, ShadertoyState *state, ShadertoyInputs *inputs, ShadertoyOutputs *outputs, ShadertoyPass pass, int channel_id) { ImageFile *image = &image_files[channel_id][pass]; memset(image->filepath, 0, sizeof(image->filepath)); switch (channel_data->type) { case SHADERTOY_RESOURCE_TEXTURE: { GetFilePath(image->filepath, channel_data->filename[0]); LoadTexture(state, image->filepath, pass, channel_id); break; } case SHADERTOY_RESOURCE_CUBE_MAP: { char *cubemap_paths[6]; for (int j = 0; j < 6; ++j) { cubemap_paths[j] = new char[1024]; GetFilePath(cubemap_paths[j], channel_data->filename[j]); if (j == 0) { strcpy(image->filepath, cubemap_paths[j]); } } LoadTexture(state, cubemap_paths, pass, channel_id); for (int j = 0; j < 6; ++j) { delete[] cubemap_paths[j]; } break; } case SHADERTOY_RESOURCE_MUSIC: { AudioFile *file = &audio_files[channel_id]; memset(file->filepath, 0, sizeof(file->filepath)); GetFilePath(file->filepath, channel_data->filename[0]); int ogg_error; stb_vorbis *ogg_data = stb_vorbis_open_filename(file->filepath, &ogg_error, NULL); file->channels = ogg_data->channels; file->samples_count = stb_vorbis_stream_length_in_samples(ogg_data) * ogg_data->channels; file->samples = (float*)malloc(sizeof(float) * file->samples_count); stb_vorbis_get_samples_float_interleaved(ogg_data, ogg_data->channels, file->samples, file->samples_count); audio_data[channel_id] = { &inputs->audio_played_samples[channel_id], &file->samples, (int)ogg_data->sample_rate, ogg_data->channels, file->samples_count / ogg_data->channels }; ShadertoyLoadAudio(state, audio_data + channel_id, SHADERTOY_IMAGE_PASS, channel_id); outputs->music_data_param[channel_id] = init_audio_output(ogg_data->channels, ogg_data->sample_rate, 32, file->samples_count * sizeof(float)); stb_vorbis_close(ogg_data); break; } case SHADERTOY_RESOURCE_MICROPHONE: { // 512 * sizeof(float) == FFT sampling data, so should be fine to use inputs->micro_data_param = init_audio_input(2, 44100, 32, 2048 * sizeof(float)); break; } case SHADERTOY_RESOURCE_KEYBOARD: case SHADERTOY_RESOURCE_NONE: break; } }
void MusicOGG::run() { while (m_isPlaying) { if (m_bufferCount < MUSIC_BUFFER_COUNT) { m_mutex.lock(); auto pBuffer = m_buffers.back(); m_buffers.pop_back(); m_mutex.unlock(); pBuffer->count = stb_vorbis_get_samples_float_interleaved(m_pStream, m_engineChannelCount, pBuffer->data.data(), m_bufferMax) * m_engineChannelCount; pBuffer->offset = 0; if (pBuffer->count) { m_mutex.lock(); m_buffers.insert(m_buffers.begin() + m_bufferCount, pBuffer); ++m_bufferCount; m_mutex.unlock(); } else { if (m_loop) { stb_vorbis_seek_start(m_pStream); m_mutex.lock(); m_buffers.push_back(pBuffer); m_mutex.unlock(); continue; } else { // Done playing! stb_vorbis_close(m_pStream); m_pStream = nullptr; m_done = true; break; } } } std::this_thread::sleep_for(std::chrono::milliseconds(10)); } }