Sunday, January 25, 2015

Project Update

Phase Vocoder

Since the last project update I've been trying to get a better understanding of the phase vocoder and how to use it for automatic pitch correction. I have some basic code running.

Figure 1: The top plot is the input signal and the bottom plot is the time stretched version 


Figure 2: The top plot is the input signal and the bottom plot is the time compressed version

The non-trivial aspect of these stretch and compression transformations is that the frequency is maintained in the output signal. This is a crucial intermediate step before doing pitch correction. The only remaining step for is a change in the sample rate to return it to the same time duration as the input signal.

I implemented the basic Phase Vocoder as covered in the paper "Improved Phase Vocoder Time-Scale Modification of Audio" by Jean Laroche and Mark Dolson.

My understanding of the algorithm is the following:
  1. Divide the input signal into frames. These frames generally are short duration (i used 512 samples). A given frames start time will overlap with the previous frame, creating a sort of signal redundancy.
  2. Each frame is moved to the frequency domain using the DTF/FFT.
  3. When generating the frequency domain representation of the output signal the magnitude of each FFT will be preserved but the phase will calculated based on the estimated frequency of the "bin" and how much time stretching/compression will be done.
  4. Each output frequency domain will be transformed back to time domain frames by using the IFFT/IDFT
  5. The output frames will be turned into a time stream by using an overlap and add method

Sunday, January 11, 2015

Project Update

Results from the DUT (interpolation filtering block)

Based on the last blog update I said that I need to finish the interpolation_filtering block soon because the project is not moving quick enough.

This weekend I completed the scoreboard for the block. The only pending issue is the rounding/scaling sub-block but I am going to move on anyway. If this proves to be a serious issue then I will come back to it.

I ran a test where I sent 500 samples to the block. Because of resampleing and filtering the block outputs 120 samples. The DUT and model produce the same results. It seems like everything is working well.

# UVM_INFO C:/questasim_10.2c/examples/julian/projects/autotune/src/tb/uvm/interpolation_filter/scoreboard_interpolation_filter.sv(174) @ 2500550.0ns: uvm_test_top.env0.sb [SCOREBOARD_CMP] tb_top_interpolation_filter.scoreboard_interpolation_filter.check_phase : dut_sample_data = 00000000, model_sample_data = 00000000, dut_sample_width = 00000012, model_sample_width = 00000012
# UVM_INFO C:/questasim_10.2c/examples/julian/projects/autotune/src/tb/uvm/interpolation_filter/scoreboard_interpolation_filter.sv(177) @ 2500550.0ns: uvm_test_top.env0.sb [SCOREBOARD_MATCH] tb_top_interpolation_filter.scoreboard_interpolation_filter.check_phase


# UVM_INFO C:/questasim_10.2c/examples/julian/projects/autotune/src/tb/uvm/interpolation_filter/scoreboard_interpolation_filter.sv(174) @ 2500550.0ns: uvm_test_top.env0.sb [SCOREBOARD_CMP] tb_top_interpolation_filter.scoreboard_interpolation_filter.check_phase : dut_sample_data = 0000000a, model_sample_data = 0000000a, dut_sample_width = 00000012, model_sample_width = 00000012
# UVM_INFO C:/questasim_10.2c/examples/julian/projects/autotune/src/tb/uvm/interpolation_filter/scoreboard_interpolation_filter.sv(177) @ 2500550.0ns: uvm_test_top.env0.sb [SCOREBOARD_MATCH] tb_top_interpolation_filter.scoreboard_interpolation_filter.check_phase


# [SCOREBOARD_CMP]   120
# [SCOREBOARD_MATCH]   120
# [TESTCASE_PASS]     1


Going Forward

I have to start spec-ing out the "Processing Engine" block. This block will take the audio samples from the interpolation filter and do the pitch correction on the stream and finally write the samples to memory. At a basic algorithm level I still have many questions about how this will work. The next few weeks I will be spending in GNU Octave to prototype the algorithm. This block will include complex numbers, FFT, trigonometric calculations so there should be lots of fun implementing it.

Tuesday, January 6, 2015

Project Update

I haven't provided an update for a couple of weeks. Here is the progress since the last update:
  • I've learned the basics of DPI. This includes the SystemVerilog coding, C coding and build script differences
  • I've defined a basic interface between SV and C. 
    • 1 API to send data to C. 
    • 1 API to run the calculations. 
    • 1 API to retrieve the data from C
  • I've implemented all of the sub-blocks included in the interpolation filter
    • Zero Stuffing
    • Filtering
    • Decimation
    • Rounding / Scaling
Looking forward:
  • I really need to finish off this block because the overall project is moving slower than I expected
  • Finalize the filter coefficients I've chosen to do low pass filtering and linear interpolation
  • Compare the RTL outputs with the C-Model outputs and find any discrepancies between the 2
  • I might need to re-design the rounding / scaling block. It is intended to keep the signal within the limits that can be represented with a fixed point system but that is not how it is implemented :(
  • MOVE ON TO THE NEXT BLOCK :)