Skip to content
nicklecoder edited this page Oct 11, 2014 · 1 revision

#Design Documentation

The functionality of LiveEVM is split between three classes: the Recorder class, the Params class, and the Amplifier class. These are documented below.

##class Params

This class is a singleton used to store data that is passed from the Recorder class to the Amplifier class.

###Members

  • static std::atomic mInstanceFlag -> Internal variable used to implement the singleton design pattern for the Params class.
  • static Params* mInstance -> Pointer to the singleton instance.
  • std::atomic mFIlter -> A value of false triggers the use of the Gaussian pyramid filter, and a true value indicates that the Laplacian pyramid algorithm is to be used in processing incoming video data before it reaches the bandpass filter.
  • std::atomic mAmpLevel -> The amount to amplify periodic changes by. The value of the amplified pixel channel is the value of the original pixel channel plus the product of 0.125 and the value of the filtered pixel channel (filtered both by the pyramid algorithm and the bandpass filter).
  • std::atomic mLowLevel -> The index of the FFT of the video at which the pass band begins. This value does not correspond to a frequency value. Instead, it indicates an index in the FFT of the video data below which all data is zeroed out.
  • std::atomic mHighLevel -> The index of the FFT of the video at which the pass band ends. This value does not correspond to a frequency value. Instead, it indicates an index in the FFT of the video data above which all data is zeroed. Note that this is the case for the first half of the FFT; the second half, which corresponds to immaginary numbers, is treated in the same way as the first half, but mirrored.

###Methods

Each member variable has corresponding set and get methods. Aside from these, there is only the getInstance() method, which returns a pointer to the singleton instance of the class.

##class Amplifier

This class is responsible for running a bandpass filter on the down-sampled video buffer and merging the result back into the original video. This section provides only a high-level overview of the design of this class.

An overview of what this class does can be retrieved by examining the run() method. This class is designed to run on its own thread apart from the Recorder class. The first step in this class is to retrieve new frames (which have already been down-sampled in order to offload some of the computation time on the Recorder class and to avoid repeating operations in other threads). Once these frames are retrieved, they are copied into a new buffer in inverted binary index order to prepare them for the FFT algorithm. Next, the FFT is computed. We then take the result, flatten the frequencies outside of the pass band, and run the inverse FFT algorithm on the result. Part of the IFFT algorithm involves scaling the output to the original magnitude; this is done simultaneously with the amplification of the signals. Finally, the result is added pixel channel by pixel channel back into the original video and made available to the Recorder class for display.

##class Recorder

This section contains only a high-level description of the design of this class.

This class operates in three stages: setup, main loop, and tear down. When setting up, the video buffer is filled with data in order to avoid problems that occur when referencing null pointers. After this is done, three instances of the Amplifier class are created. Upon creation, they copy the video buffer into their own local buffers and set up a staggered cursor system that allows each one to focus on producing output for non-overlapping subsections of the circular buffer. Once setup is complete, the main loop is entered, and it executes the following steps:

  • Retrieve a new frame
  • Down-sample that frame using either Gaussian or Laplacian image pyramids as indicated by the user.
  • If enough new frames have been retrieved, signal the next Amplifier thread in a thread queue to run.
  • Display both the clean and amplified video frame at the current cursor position.
  • Exit the loop if the user hits escape.
  • Advance the cursor.

When the user hits the escape key, this main loop terminates and all running threads are signaled to terminate. The Recorder thread does not wait for worker threads to terminate.

##main()

This function does no more than instantiate the Recorder class and run it.

Clone this wiki locally