Guest User

Untitled

a guest
Apr 14th, 2020
324
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.08 KB | None | 0 0
  1. #include <cinttypes>
  2. #include <cmath>
  3. #include <cstdlib>
  4. #include <iostream>
  5. #include <memory>
  6. #include <string>
  7. #include <vector>
  8.  
  9. #include <sndfile.h>
  10. #include <SDL2/SDL.h>
  11.  
  12. //maybe add timer and cross?
  13.  
  14. //chunks to read in and write to the file
  15. int buff_size = 1024 * 128;
  16.  
  17. constexpr int frame_rate = 45;
  18.  
  19. constexpr int FRAME_X = 600;
  20. constexpr int FRAME_Y = 600;
  21.  
  22. constexpr double SUB_FRAME_RATIO = 0.8;
  23.  
  24. //the void* to be passed for rendering
  25. struct current_audio_buffer
  26. {
  27.     const int* data;
  28.     volatile int  start_index;
  29.     const int  samples_per_frame;
  30.     SDL_Renderer *rend;
  31.     unsigned char green;
  32.     bool up;
  33. };
  34.  
  35. int render_callback( Uint32 interval, void *param )
  36. {
  37.  
  38.     Uint32 TICK_START = SDL_GetTicks();
  39.  
  40.     struct current_audio_buffer* ab = ( current_audio_buffer* ) ( param );
  41.  
  42.     SDL_SetRenderDrawColor(ab->rend, 0x00, 0x00, 0x00, 0xFF);
  43.     SDL_RenderClear(ab->rend);
  44.  
  45.     const int SQ_SIZE       = std::min(FRAME_X, FRAME_Y);
  46.     const int divide_scale  = (INT32_MAX/(SQ_SIZE * SUB_FRAME_RATIO/2));
  47.     const int X_CENTER      = FRAME_X/2;
  48.     const int Y_CENTER      = FRAME_Y/2;
  49.  
  50.     // have color shift over time
  51.     if (ab->green == 0xFF && ab->up == 1)
  52.     {
  53.         ab->up = 0;
  54.     }
  55.     if (ab->green == 0x00 && ab->up == 0)
  56.     {
  57.         ab->up = 1;
  58.     }
  59.  
  60.     ab->green += (ab->up == 1 ? 1 : -1);
  61.  
  62. // draw simple grid
  63.  
  64.     SDL_SetRenderDrawColor( ab->rend, 0x10,0x10,0x10,0xFF);
  65.  
  66.     SDL_RenderDrawLine( ab->rend,
  67.                         X_CENTER, 0,
  68.                         X_CENTER, FRAME_Y
  69.                       );
  70.  
  71.     SDL_RenderDrawLine( ab->rend,
  72.                         0      , Y_CENTER,
  73.                         FRAME_X, Y_CENTER
  74.                       );
  75.  
  76.     SDL_RenderDrawLine( ab->rend,
  77.                         0, 0,
  78.                         FRAME_X, FRAME_Y
  79.                       );
  80.  
  81.     SDL_RenderDrawLine( ab->rend,
  82.                         0      , FRAME_Y,
  83.                         FRAME_X, 0
  84.                       );
  85.  
  86.     for ( int i = ab->start_index; i < ab->start_index + ab->samples_per_frame - 2; i+=2 )
  87.     {
  88.         //if ( radius <= 0x20000000 )
  89.         //{
  90.         //    SDL_SetRenderDrawColor( ab->rend, 0x00 + radius_m + ab->green / 2, ab->green, 0xFF - radius_m - ab->green / 2, 0xFF );
  91.         //}
  92.         //else
  93.         //{
  94.         //}
  95.  
  96.         SDL_SetRenderDrawColor(ab->rend, 0xFF - ab->green, ab->green, 0xFF, 0xFF);
  97.  
  98.         SDL_RenderDrawPoint (ab->rend,
  99.                               ((ab->data)[i])          / (divide_scale) + X_CENTER,
  100.                               ( -1*(ab->data)[i + 1] ) / (divide_scale) + Y_CENTER
  101.                             );
  102.  
  103.     }
  104.  
  105.     ab->start_index = (ab->start_index + ab->samples_per_frame) &  (~1);
  106.  
  107.     SDL_RenderPresent(ab->rend);
  108.  
  109.     //set the next frame to be rendered in 1000/framerate minus the time we spent here
  110.     return 1000/frame_rate - (SDL_GetTicks() - TICK_START);
  111. }
  112.  
  113. int main(int argc, char** argv)
  114. {
  115.  
  116.     bool quit = false;
  117.     //find file name to open
  118.     if ( argc != 2 )
  119.     {
  120.         std::cerr << "Usage \n"
  121.                   << "XY Visualize <wav or flac file to visualize>" << std::endl;
  122.         std::exit( 1 );
  123.     }
  124.  
  125.     std::string in_name = argv[1];
  126.     if (in_name.substr( in_name.size() - 4, 4 ) != ".wav" && in_name.substr( in_name.size() - 5, 5 ) != ".flac")
  127.     {
  128.         std::cerr << "Must input wav or flac file!!!" << std::endl;
  129.         std::exit(2);
  130.     }
  131.  
  132.     SF_INFO info_in [1];
  133.     info_in->format = 0;
  134.  
  135.     SNDFILE*  file_in = sf_open(in_name.c_str(),SFM_READ, info_in);
  136.  
  137.     buff_size = buff_size + (buff_size % info_in->channels);
  138.  
  139.     // in buffer to read in from the file
  140.     // maybe have a second buffer to read from disc the next bytes asynchoronously?
  141.     std::unique_ptr<int[]> in_buffer = std::unique_ptr<int[]>(new int[buff_size]);
  142.  
  143.     SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_TIMER);
  144.     SDL_AudioSpec want, have;
  145.     SDL_AudioDeviceID dev;
  146.  
  147.     SDL_Window   *window;
  148.     SDL_Renderer *renderer;
  149.     SDL_Event    e;
  150.  
  151.     SDL_CreateWindowAndRenderer( FRAME_X,
  152.                                  FRAME_Y,
  153.                                  SDL_WINDOW_OPENGL, //| SDL_WINDOW_RESIZABLE,
  154.                                  &window,
  155.                                  &renderer );
  156.  
  157.     std::string file_name;
  158.     {
  159.         int found = in_name.find_last_of("/\\");
  160.         if (found == std::string::npos)
  161.         {
  162.             file_name = in_name;
  163.         }
  164.         else
  165.         {
  166.             file_name = in_name.substr(found + 1);
  167.         }
  168.     }
  169.  
  170.     std::string window_name = (std::string)"XY Visualize: " + file_name;
  171.     SDL_SetWindowTitle(window, window_name.c_str());
  172.  
  173.     SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
  174.     SDL_PumpEvents();
  175.  
  176.     SDL_memset(&want, 0, sizeof(want));
  177.     SDL_memset(&have, 0, sizeof(have));
  178.  
  179.     //make the SDL match with the data we have
  180.     want.freq     = info_in->samplerate;
  181.     want.format   = AUDIO_S32;
  182.     want.channels = info_in->channels;
  183.     want.samples  = buff_size * sizeof(*(in_buffer.get()));
  184.  
  185.     //open device
  186.     dev = SDL_OpenAudioDevice(NULL, 0, &want, &have, SDL_AUDIO_ALLOW_FORMAT_CHANGE);
  187.  
  188.     const int frames_per_buffer_read = (buff_size * frame_rate / (info_in->channels * info_in->samplerate));
  189.     const int samples_per_frame      = ((info_in->channels * info_in->samplerate)/ frame_rate);
  190.  
  191.     //make struct to pass to callbacks
  192.     struct current_audio_buffer AUDIO_BUFFER =
  193.     {
  194.         .data              = in_buffer.get(),
  195.         .start_index       = 0,
  196.         .samples_per_frame = samples_per_frame,
  197.         .rend              = renderer,
  198.         .green             = 0,
  199.         .up                = 1
  200.     };
  201.  
  202.     //unpause audio
  203.     SDL_PauseAudioDevice(dev, 0);
  204.  
  205.     Uint32 TICK_START = SDL_GetTicks();
  206.  
  207.     //read data from queue, and start timers for frame rendering
  208.     while (int read_in = sf_read_int(file_in, in_buffer.get(), buff_size))
  209.     {
  210.         if (quit)
  211.         {
  212.             break;
  213.         }
  214.         AUDIO_BUFFER.start_index = 0;
  215.         SDL_QueueAudio(dev, in_buffer.get(), sizeof(*(in_buffer.get())) * read_in );
  216.  
  217.         SDL_TimerID TID = SDL_AddTimer( static_cast<Uint32>(1000 / frame_rate),
  218.                                          (SDL_TimerCallback)render_callback,
  219.                                          (void*)(&AUDIO_BUFFER));
  220.  
  221.  
  222.         SDL_Delay(500 * read_in/(info_in->channels * info_in->samplerate) - (SDL_GetTicks() - TICK_START));
  223.  
  224.         SDL_PumpEvents();
  225.  
  226.         while (SDL_PollEvent(&e))
  227.         {
  228.             //If user closes the window
  229.             if (e.type == SDL_QUIT)
  230.             {
  231.                 quit = true;
  232.             }
  233.         }
  234.  
  235.         SDL_Delay(1000 * read_in / (info_in->channels * info_in->samplerate) - (SDL_GetTicks() - TICK_START));
  236.         TICK_START = SDL_GetTicks();
  237.         SDL_RemoveTimer(TID);
  238.     }
  239.  
  240.     //cleanup
  241.     sf_close(file_in);
  242.  
  243.     SDL_CloseAudioDevice(dev);
  244.     SDL_DestroyRenderer(renderer);
  245.     SDL_DestroyWindow(window);
  246.  
  247.     SDL_Quit();
  248.  
  249.     return 0;
  250. }
Advertisement
Add Comment
Please, Sign In to add comment