Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <cinttypes>
- #include <cmath>
- #include <cstdlib>
- #include <iostream>
- #include <memory>
- #include <string>
- #include <vector>
- #include <sndfile.h>
- #include <SDL2/SDL.h>
- //maybe add timer and cross?
- //chunks to read in and write to the file
- int buff_size = 1024 * 128;
- constexpr int frame_rate = 45;
- constexpr int FRAME_X = 600;
- constexpr int FRAME_Y = 600;
- constexpr double SUB_FRAME_RATIO = 0.8;
- //the void* to be passed for rendering
- struct current_audio_buffer
- {
- const int* data;
- volatile int start_index;
- const int samples_per_frame;
- SDL_Renderer *rend;
- unsigned char green;
- bool up;
- };
- int render_callback( Uint32 interval, void *param )
- {
- Uint32 TICK_START = SDL_GetTicks();
- struct current_audio_buffer* ab = ( current_audio_buffer* ) ( param );
- SDL_SetRenderDrawColor(ab->rend, 0x00, 0x00, 0x00, 0xFF);
- SDL_RenderClear(ab->rend);
- const int SQ_SIZE = std::min(FRAME_X, FRAME_Y);
- const int divide_scale = (INT32_MAX/(SQ_SIZE * SUB_FRAME_RATIO/2));
- const int X_CENTER = FRAME_X/2;
- const int Y_CENTER = FRAME_Y/2;
- // have color shift over time
- if (ab->green == 0xFF && ab->up == 1)
- {
- ab->up = 0;
- }
- if (ab->green == 0x00 && ab->up == 0)
- {
- ab->up = 1;
- }
- ab->green += (ab->up == 1 ? 1 : -1);
- // draw simple grid
- SDL_SetRenderDrawColor( ab->rend, 0x10,0x10,0x10,0xFF);
- SDL_RenderDrawLine( ab->rend,
- X_CENTER, 0,
- X_CENTER, FRAME_Y
- );
- SDL_RenderDrawLine( ab->rend,
- 0 , Y_CENTER,
- FRAME_X, Y_CENTER
- );
- SDL_RenderDrawLine( ab->rend,
- 0, 0,
- FRAME_X, FRAME_Y
- );
- SDL_RenderDrawLine( ab->rend,
- 0 , FRAME_Y,
- FRAME_X, 0
- );
- for ( int i = ab->start_index; i < ab->start_index + ab->samples_per_frame - 2; i+=2 )
- {
- //if ( radius <= 0x20000000 )
- //{
- // SDL_SetRenderDrawColor( ab->rend, 0x00 + radius_m + ab->green / 2, ab->green, 0xFF - radius_m - ab->green / 2, 0xFF );
- //}
- //else
- //{
- //}
- SDL_SetRenderDrawColor(ab->rend, 0xFF - ab->green, ab->green, 0xFF, 0xFF);
- SDL_RenderDrawPoint (ab->rend,
- ((ab->data)[i]) / (divide_scale) + X_CENTER,
- ( -1*(ab->data)[i + 1] ) / (divide_scale) + Y_CENTER
- );
- }
- ab->start_index = (ab->start_index + ab->samples_per_frame) & (~1);
- SDL_RenderPresent(ab->rend);
- //set the next frame to be rendered in 1000/framerate minus the time we spent here
- return 1000/frame_rate - (SDL_GetTicks() - TICK_START);
- }
- int main(int argc, char** argv)
- {
- bool quit = false;
- //find file name to open
- if ( argc != 2 )
- {
- std::cerr << "Usage \n"
- << "XY Visualize <wav or flac file to visualize>" << std::endl;
- std::exit( 1 );
- }
- std::string in_name = argv[1];
- if (in_name.substr( in_name.size() - 4, 4 ) != ".wav" && in_name.substr( in_name.size() - 5, 5 ) != ".flac")
- {
- std::cerr << "Must input wav or flac file!!!" << std::endl;
- std::exit(2);
- }
- SF_INFO info_in [1];
- info_in->format = 0;
- SNDFILE* file_in = sf_open(in_name.c_str(),SFM_READ, info_in);
- buff_size = buff_size + (buff_size % info_in->channels);
- // in buffer to read in from the file
- // maybe have a second buffer to read from disc the next bytes asynchoronously?
- std::unique_ptr<int[]> in_buffer = std::unique_ptr<int[]>(new int[buff_size]);
- SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_TIMER);
- SDL_AudioSpec want, have;
- SDL_AudioDeviceID dev;
- SDL_Window *window;
- SDL_Renderer *renderer;
- SDL_Event e;
- SDL_CreateWindowAndRenderer( FRAME_X,
- FRAME_Y,
- SDL_WINDOW_OPENGL, //| SDL_WINDOW_RESIZABLE,
- &window,
- &renderer );
- std::string file_name;
- {
- int found = in_name.find_last_of("/\\");
- if (found == std::string::npos)
- {
- file_name = in_name;
- }
- else
- {
- file_name = in_name.substr(found + 1);
- }
- }
- std::string window_name = (std::string)"XY Visualize: " + file_name;
- SDL_SetWindowTitle(window, window_name.c_str());
- SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
- SDL_PumpEvents();
- SDL_memset(&want, 0, sizeof(want));
- SDL_memset(&have, 0, sizeof(have));
- //make the SDL match with the data we have
- want.freq = info_in->samplerate;
- want.format = AUDIO_S32;
- want.channels = info_in->channels;
- want.samples = buff_size * sizeof(*(in_buffer.get()));
- //open device
- dev = SDL_OpenAudioDevice(NULL, 0, &want, &have, SDL_AUDIO_ALLOW_FORMAT_CHANGE);
- const int frames_per_buffer_read = (buff_size * frame_rate / (info_in->channels * info_in->samplerate));
- const int samples_per_frame = ((info_in->channels * info_in->samplerate)/ frame_rate);
- //make struct to pass to callbacks
- struct current_audio_buffer AUDIO_BUFFER =
- {
- .data = in_buffer.get(),
- .start_index = 0,
- .samples_per_frame = samples_per_frame,
- .rend = renderer,
- .green = 0,
- .up = 1
- };
- //unpause audio
- SDL_PauseAudioDevice(dev, 0);
- Uint32 TICK_START = SDL_GetTicks();
- //read data from queue, and start timers for frame rendering
- while (int read_in = sf_read_int(file_in, in_buffer.get(), buff_size))
- {
- if (quit)
- {
- break;
- }
- AUDIO_BUFFER.start_index = 0;
- SDL_QueueAudio(dev, in_buffer.get(), sizeof(*(in_buffer.get())) * read_in );
- SDL_TimerID TID = SDL_AddTimer( static_cast<Uint32>(1000 / frame_rate),
- (SDL_TimerCallback)render_callback,
- (void*)(&AUDIO_BUFFER));
- SDL_Delay(500 * read_in/(info_in->channels * info_in->samplerate) - (SDL_GetTicks() - TICK_START));
- SDL_PumpEvents();
- while (SDL_PollEvent(&e))
- {
- //If user closes the window
- if (e.type == SDL_QUIT)
- {
- quit = true;
- }
- }
- SDL_Delay(1000 * read_in / (info_in->channels * info_in->samplerate) - (SDL_GetTicks() - TICK_START));
- TICK_START = SDL_GetTicks();
- SDL_RemoveTimer(TID);
- }
- //cleanup
- sf_close(file_in);
- SDL_CloseAudioDevice(dev);
- SDL_DestroyRenderer(renderer);
- SDL_DestroyWindow(window);
- SDL_Quit();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment