<commit_before>// FreqShifter_FD
//
// Demonstrate frequency shifting via frequency domain processin.
//
// Created: <NAME> (OpenAudio) Aug 2019
//
// Approach: This processing is performed in the frequency domain.
//    Frequencies can only be shifted by an integer number of bins,
//    so small frequency shifts are not possible.  For example, for
//    a sample rate of 44.1kHz, and when using N=256, one can only
//    shift frequencies in multiples of 44.1/256 = 172.3 Hz.
//
//    This processing is performed in the frequency domain where
//    we take the FFT, shift the bins upward or downward, take
//    the IFFT, and listen to the results.  In effect, this is
//    single sideband modulation, which will sound very unnatural
//    (like robot voices!).  Maybe you'll like it, or maybe not.
//    Probably not, unless you like weird.  ;)
//
//    You can shift frequencies upward or downward with this algorithm.
//
// Frequency Domain Processing:
//    * Take samples in the time domain
//    * Take FFT to convert to frequency domain
//    * Manipulate the frequency bins to do the freqyebct shifting
//    * Take IFFT to convert back to time domain
//    * Send samples back to the audio interface
//
// Built for the Tympan library for Teensy 3.6-based hardware
//
// MIT License.  Use at your own risk.
//

#include <Tympan_Library.h>
#include "SerialManager.h"

//set the sample rate and block size
const float sample_rate_Hz = 44117.f; ; //24000 or 44117 (or other frequencies in the table in AudioOutputI2S_F32)
const int audio_block_samples = 64;     //for freq domain processing choose a power of 2 (16, 32, 64, 128) but no higher than 128
AudioSettings_F32 audio_settings(sample_rate_Hz, audio_block_samples);

//create audio library objects for handling the audio
Tympan                        audioHardware(TympanRev::D);     //do TympanRev::C or TympanRev::D
AudioInputI2S_F32             i2s_in(audio_settings);          //Digital audio *from* the Tympan AIC.
AudioEffectFreqShiftFD_F32    freqShift(audio_settings);       //create the frequency-domain processing block
AudioEffectGain_F32           gain1;                           //Applies digital gain to audio data.
AudioOutputI2S_F32            i2s_out(audio_settings);         //Digital audio out *to* the Tympan AIC.

//Make all of the audio connections
AudioConnection_F32       patchCord10(i2s_in, 0, freqShift, 0);   //use the Left input
AudioConnection_F32       patchCord20(freqShift, 0, gain1, 0);     //connect to gain
AudioConnection_F32       patchCord30(gain1, 0, i2s_out, 0);      //connect to the left output
AudioConnection_F32       patchCord40(gain1, 0, i2s_out, 1);       //connect to the right output


//control display and serial interaction
bool enable_printCPUandMemory = false;
void togglePrintMemoryAndCPU(void) { enable_printCPUandMemory = !enable_printCPUandMemory; };
SerialManager serialManager(audioHardware);
#define mySerial audioHardware   //audioHardware is a printable stream!

//inputs and levels
float input_gain_dB = 15.0f; //gain on the microphone
float vol_knob_gain_dB = 0.0;      //will be overridden by volume knob
void switchToPCBMics(void) {
  mySerial.println("Switching to PCB Mics.");
  audioHardware.inputSelect(TYMPAN_INPUT_ON_BOARD_MIC); // use the microphone jack - defaults to mic bias OFF
  audioHardware.setInputGain_dB(input_gain_dB);
}
void switchToLineInOnMicJack(void) {
  mySerial.println("Switching to Line-in on Mic Jack.");
  audioHardware.inputSelect(TYMPAN_INPUT_JACK_AS_LINEIN); // use the microphone jack - defaults to mic bias OFF  
  audioHardware.setInputGain_dB(0.0);
}
void switchToMicInOnMicJack(void) {
  mySerial.println("Switching to Mic-In on Mic Jack.");
  audioHardware.inputSelect(TYMPAN_INPUT_JACK_AS_MIC); // use the microphone jack - defaults to mic bias OFF   
  audioHardware.setEnableStereoExtMicBias(true);  //put the mic bias on both channels
  audioHardware.setInputGain_dB(input_gain_dB);
}
      
// define the setup() function, the function that is called once when the device is booting
void setup() {
  audioHardware.beginBothSerial(); delay(1000);
  mySerial.println("freqShifter: starting setup()...");
  mySerial.print("    : sample rate (Hz) = ");  mySerial.println(audio_settings.sample_rate_Hz);
  mySerial.print("    : block size (samples) = ");  mySerial.println(audio_settings.audio_block_samples);

  // Audio connections require memory to work.  For more
  // detailed information, see the MemoryAndCpuUsage example
  AudioMemory_F32(40, audio_settings);

  // Configure the FFT parameters algorithm
  int overlap_factor = 4;  //set to 2, 4 or 8...which yields 50%, 75%, or 87.5% overlap (8x)
  int N_FFT = audio_block_samples * overlap_factor;  
  Serial.print("    : N_FFT = "); Serial.println(N_FFT);
  freqShift.setup(audio_settings, N_FFT); //do after AudioMemory_F32();

  //configure the frequency shifting
  float Hz_per_bin = audio_settings.sample_rate_Hz / ((float)N_FFT);
  float shiftFreq_Hz;
  int shift_bins;
  #if 1
    shiftFreq_Hz = 750.0; //shift audio upward a bit
  #else
    shiftFreq_Hz = -37000.0; //or, if you raise the sample rate to 96000, you can bring ultrasound down into audible band!
  #endif
  if (shiftFreq_Hz >= 0) {
    shift_bins = (int)(shiftFreq_Hz / Hz_per_bin + 0.5);  //round to nearest bin
  } else {
    shift_bins = (int)(shiftFreq_Hz / Hz_per_bin - 0.5);  //round to nearest bin
  }
  shiftFreq_Hz = shift_bins * Hz_per_bin;
  Serial.print("Setting shift to "); Serial.print(shiftFreq_Hz); Serial.print(" Hz, which is "); Serial.print(shift_bins); Serial.println(" bins");
  freqShift.setShift_bins(shift_bins); //0 is no ffreq shifting.
 
  //Enable the Tympan to start the audio flowing!
  audioHardware.enable(); // activate AIC

  //setup DC-blocking highpass filter running in the ADC hardware itself
  float cutoff_Hz = 60.0;  //set the default cutoff frequency for the highpass filter
  audioHardware.setHPFonADC(true,cutoff_Hz,audio_settings.sample_rate_Hz); //set to false to disble

  //Choose the desired input
  switchToPCBMics();        //use PCB mics as input
  //switchToMicInOnMicJack(); //use Mic jack as mic input (ie, with mic bias)
  //switchToLineInOnMicJack();  //use Mic jack as line input (ie, no mic bias)
  
  //Set the desired volume levels
  audioHardware.volume_dB(0);                   // headphone amplifier.  -63.6 to +24 dB in 0.5dB steps.
   
  // configure the blue potentiometer
  servicePotentiometer(millis(),0); //update based on the knob setting the "0" is not relevant here.
<commit_msg>FrequencyShifter: Clarify setting of shift amount<commit_after>// FreqShifter_FD
//
// Demonstrate frequency shifting via frequency domain processin.
//
// Created: <NAME> (OpenAudio) Aug 2019
//
// Approach: This processing is performed in the frequency domain.
//    Frequencies can only be shifted by an integer number of bins,
//    so small frequency shifts are not possible.  For example, for
//    a sample rate of 44.1kHz, and when using N=256, one can only
//    shift frequencies in multiples of 44.1/256 = 172.3 Hz.
//
//    This processing is performed in the frequency domain where
//    we take the FFT, shift the bins upward or downward, take
//    the IFFT, and listen to the results.  In effect, this is
//    single sideband modulation, which will sound very unnatural
//    (like robot voices!).  Maybe you'll like it, or maybe not.
//    Probably not, unless you like weird.  ;)
//
//    You can shift frequencies upward or downward with this algorithm.
//
// Frequency Domain Processing:
//    * Take samples in the time domain
//    * Take FFT to convert to frequency domain
//    * Manipulate the frequency bins to do the freqyebct shifting
//    * Take IFFT to convert back to time domain
//    * Send samples back to the audio interface
//
// Built for the Tympan library for Teensy 3.6-based hardware
//
// MIT License.  Use at your own risk.
//

#include <Tympan_Library.h>
#include "SerialManager.h"

//set the sample rate and block size
const float sample_rate_Hz = 44117.f; ; //24000 or 44117 (or other frequencies in the table in AudioOutputI2S_F32)
const int audio_block_samples = 64;     //for freq domain processing choose a power of 2 (16, 32, 64, 128) but no higher than 128
AudioSettings_F32 audio_settings(sample_rate_Hz, audio_block_samples);

//create audio library objects for handling the audio
Tympan                        audioHardware(TympanRev::D);     //do TympanRev::C or TympanRev::D
AudioInputI2S_F32             i2s_in(audio_settings);          //Digital audio *from* the Tympan AIC.
AudioEffectFreqShiftFD_F32    freqShift(audio_settings);       //create the frequency-domain processing block
AudioEffectGain_F32           gain1;                           //Applies digital gain to audio data.
AudioOutputI2S_F32            i2s_out(audio_settings);         //Digital audio out *to* the Tympan AIC.

//Make all of the audio connections
AudioConnection_F32       patchCord10(i2s_in, 0, freqShift, 0);   //use the Left input
AudioConnection_F32       patchCord20(freqShift, 0, gain1, 0);     //connect to gain
AudioConnection_F32       patchCord30(gain1, 0, i2s_out, 0);      //connect to the left output
AudioConnection_F32       patchCord40(gain1, 0, i2s_out, 1);       //connect to the right output


//control display and serial interaction
bool enable_printCPUandMemory = false;
void togglePrintMemoryAndCPU(void) { enable_printCPUandMemory = !enable_printCPUandMemory; };
SerialManager serialManager(audioHardware);
#define mySerial audioHardware   //audioHardware is a printable stream!

//inputs and levels
float input_gain_dB = 15.0f; //gain on the microphone
float vol_knob_gain_dB = 0.0;      //will be overridden by volume knob
void switchToPCBMics(void) {
  mySerial.println("Switching to PCB Mics.");
  audioHardware.inputSelect(TYMPAN_INPUT_ON_BOARD_MIC); // use the microphone jack - defaults to mic bias OFF
  audioHardware.setInputGain_dB(input_gain_dB);
}
void switchToLineInOnMicJack(void) {
  mySerial.println("Switching to Line-in on Mic Jack.");
  audioHardware.inputSelect(TYMPAN_INPUT_JACK_AS_LINEIN); // use the microphone jack - defaults to mic bias OFF  
  audioHardware.setInputGain_dB(0.0);
}
void switchToMicInOnMicJack(void) {
  mySerial.println("Switching to Mic-In on Mic Jack.");
  audioHardware.inputSelect(TYMPAN_INPUT_JACK_AS_MIC); // use the microphone jack - defaults to mic bias OFF   
  audioHardware.setEnableStereoExtMicBias(true);  //put the mic bias on both channels
  audioHardware.setInputGain_dB(input_gain_dB);
}
      
// define the setup() function, the function that is called once when the device is booting
void setup() {
  audioHardware.beginBothSerial(); delay(1000);
  mySerial.println("freqShifter: starting setup()...");
  mySerial.print("    : sample rate (Hz) = ");  mySerial.println(audio_settings.sample_rate_Hz);
  mySerial.print("    : block size (samples) = ");  mySerial.println(audio_settings.audio_block_samples);

  // Audio connections require memory to work.  For more
  // detailed information, see the MemoryAndCpuUsage example
  AudioMemory_F32(40, audio_settings);

  // Configure the FFT parameters algorithm
  int overlap_factor = 4;  //set to 2, 4 or 8...which yields 50%, 75%, or 87.5% overlap (8x)
  int N_FFT = audio_block_samples * overlap_factor;  
  Serial.print("    : N_FFT = "); Serial.println(N_FFT);
  freqShift.setup(audio_settings, N_FFT); //do after AudioMemory_F32();

  //configure the frequency shifting
  float shiftFreq_Hz = 750.0; //shift audio upward a bit
  float Hz_per_bin = audio_settings.sample_rate_Hz / ((float)N_FFT);
  int shift_bins = (int)(shiftFreq_Hz / Hz_per_bin + 0.5);  //round to nearest bin
  shiftFreq_Hz = shift_bins * Hz_per_bin;
  Serial.print("Setting shift to "); Serial.print(shiftFreq_Hz); Serial.print(" Hz, which is "); Serial.print(shift_bins); Serial.println(" bins");
  freqShift.setShift_bins(shift_bins); //0 is no ffreq shifting.
 
  //Enable the Tympan to start the audio flowing!
  audioHardware.enable(); // activate AIC

  //setup DC-blocking highpass filter running in the ADC hardware itself
  float cutoff_Hz = 60.0;  //set the default cutoff frequency for the highpass filter
  audioHardware.setHPFonADC(true,cutoff_Hz,audio_settings.sample_rate_Hz); //set to false to disble

  //Choose the desired input
  switchToPCBMics();        //use PCB mics as input
  //switchToMicInOnMicJack(); //use Mic jack as mic input (ie, with mic bias)
  //switchToLineInOnMicJack();  //use Mic jack as line input (ie, no mic bias)
  
  //Set the desired volume levels
  audioHardware.volume_dB(0);                   // headphone amplifier.  -63.6 to +24 dB in 0.5dB steps.
   
  // configure the blue potentiometer
  servicePotentiometer(millis(),0); //update based on the knob setting the "0" is not relevant here.

{'fraction_non_alphanumeric': 0.09257098405289771, 'fraction_numerical': 0.024348502528199145, 'mean_word_length': 3.526760563380282, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 8, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6616104', 'n_tokens_mistral': 4231, 'n_tokens_neox': 3886, 'n_words': 1358}