Browse Source

tone: generating 440Hz tone

TODO: separate the playback execution in a different thread.
Douglas Andreani 2 years ago
parent
commit
42253a9d69
4 changed files with 98 additions and 75 deletions
  1. 90 69
      src/AudioPlayer.cpp
  2. 1 1
      src/AudioPlayer.h
  3. 3 1
      src/CMakeLists.txt
  4. 4 4
      src/main.cpp

+ 90 - 69
src/AudioPlayer.cpp

@@ -4,92 +4,113 @@
 #include <cassert>
 #include <cmath>
 
-struct AudioData {
+struct AudioData
+{
   float *data;
 };
 
-namespace Audio {
+namespace Audio
+{
 
-AudioPlayer::AudioPlayer() {
+  AudioPlayer::AudioPlayer()
+  {
 
-  spdlog::info("Started Audio Player {} {}", m_frequency, m_sample_rate);
+    spdlog::info("Started Audio Player {} {}", m_frequency, m_sample_rate);
 
-  generate_samples();
-  config = ma_device_config_init(ma_device_type_playback);
-  config.playback.format = ma_format_f32;
-  config.playback.channels = 2;
-  config.sampleRate = m_sample_rate;
-  config.dataCallback = data_callback;
-  AudioData ad;
-  ad.data = m_sample.data();
-  //ad.length = m_sample.size();
- // ad.frequency = m_frequency;
- // ad.sample_rate = m_sample_rate;
-  config.pUserData = static_cast<float *>(m_sample.data());
-  ma_device_init(NULL, &config, &device);
+    config = ma_device_config_init(ma_device_type_playback);
+    config.playback.format = ma_format_f32;
+    config.playback.channels = 2;
+    config.sampleRate = 0;
+    config.dataCallback = data_callback;
 
-  spdlog::info("Device: {} Channels: {}, Sample Rate: {}/{}", device.playback.name, device.playback.channels, device.sampleRate, device.playback.internalSampleRate);
-}
+    m_sample = std::vector<float>(64, 440.0f);
+    generate_samples();
 
-void AudioPlayer::play() {
+  }
 
-  m_is_playing = true;
-  ma_device_start(&device);
-}
+  void AudioPlayer::play()
+  {
+
+    std::vector<float> synthetic_wave = std::vector<float>(10 * m_sample_rate, m_frequency);
+    for (int i = 0; i < synthetic_wave.size(); ++i) {
+      synthetic_wave[i] = next_sample() * m_amplitude;
+      
+    }
+    
+    config.pUserData = (void *)(synthetic_wave.data());
+    
+    spdlog::info("synthetic wave is: {} {}", synthetic_wave.size(), synthetic_wave.data()[10]);
+    
+    
+    if (ma_device_init(NULL, &config, &device) != MA_SUCCESS) {
+      spdlog::error("could not intialize device");
+      exit(EXIT_FAILURE);
+    }
+    spdlog::info("Device: {} Channels: {}, Sample Rate: {}/{}", device.playback.name, device.playback.channels, device.sampleRate, device.playback.internalSampleRate);
+    s_frame_pos = 10;
+    m_is_playing = true;
+    
+    spdlog::info("Playing!");
+    ma_device_start(&device);
+  }
 
-void AudioPlayer::pause() {
-  m_is_playing = false;
-  ma_device_uninit(&device);
-}
+  void AudioPlayer::pause()
+  {
+    m_is_playing = false;
+    ma_device_uninit(&device);
+  }
 
-bool AudioPlayer::is_playing() { return m_is_playing; }
+  bool AudioPlayer::is_playing() { return m_is_playing; }
 
-void AudioPlayer::generate_samples() {
-  float tick = m_frequency / m_sample_rate;
+  void AudioPlayer::generate_samples()
+  {
+    const size_t length = 64;
+   
+    for (int i = 0; i < length; ++i ) {
+      m_sample[i] = sinf(2 * PI_F * i / length);
+      //spdlog::info("Added: [{}] = {} ", i, m_sample[i]);
+    }
 
-  for (float i = 0.f; i < 2 * PI_F; i += tick) {
-    m_sample.push_back(next_sample());
+    spdlog::info("Have {} samples", m_sample.size());
   }
 
-  spdlog::info("Have {} samples", m_sample.size());
-}
+  float AudioPlayer::next_sample()
+  {
+    auto idx = get_next_frame_pos(m_frequency, m_sample_rate);
+    return m_sample[idx];
 
-float AudioPlayer::next_sample() {
-  m_phase += m_frequency / m_sample_rate;
-  if (m_phase >= 1.0) {
-    m_phase -= floorf(m_phase);
   }
-  return sinf(2 * PI_F * m_phase) * m_amplitude;
-}
-
-int AudioPlayer::get_next_frame_pos(float frequency, float sample_rate) {
-  float tick = frequency / sample_rate;
-  float max =  PI_F / tick;
-  s_frame_pos++;
-  if (s_frame_pos >= max) {
-    s_frame_pos = 0;
+
+  int AudioPlayer::get_next_frame_pos(float frequency, float sample_rate)
+  {
+    float increment = 64 * frequency / sample_rate;
+    int v = (s_frame_pos + increment);
+    int idx = (int) (floorf(v % 64));
+    s_frame_pos++;
+    
+    return idx;
   }
-  return s_frame_pos;
-}
-
-void AudioPlayer::data_callback(ma_device *device, void *output,
-                                const void *input, ma_uint32 frame_count) {
-  float *output_f32 = (float *)output;
-  float *ad = (float *)(device->pUserData);
-
-  int j = get_next_frame_pos(440.0f, 44100.f);
- // spdlog::info("Got frame pos: {} with length: {} and value: {}", j, 0, (float)ad[j]);
-  //if (ad->length == 0)
-  //  return;
-
-  for (uint32_t curFrame = 0; curFrame < frame_count; curFrame+=2) {
-    //assert(j < ad->length);
-    // spdlog::info("Got value {} -> {}", j, ad->data[j]);
-    float value = (float)ad[j];
-    output_f32[curFrame * 2 + 0] = value;
-    output_f32[curFrame * 2 + 1] = value;
-    //if (++j >= ad->length)
-    //  j = 0;
+
+  void AudioPlayer::data_callback(ma_device *device, void *output,
+                                  const void *input, ma_uint32 frame_count)
+  {
+    float *output_f32 = (float *)output;
+    float *ad = (float *)(device->pUserData);
+
+    // spdlog::info("Got frame pos: {} with length: {} and value: {}", j, 0, (float)ad[j]);
+    // if (ad->length == 0)
+    //  return;
+
+    for (uint32_t curFrame = 0; curFrame < frame_count; curFrame++)
+    {
+      int j = get_next_frame_pos(440.0f, 48000.f);
+      // assert(j < ad->length);
+      //spdlog::info("Got value {} -> {}", j, ad[j]);
+      float value = (float)ad[j];
+      output_f32[curFrame * 2 + 0] = value;
+      output_f32[curFrame * 2 + 1] = value;
+      // if (++j >= ad->length)
+      //   j = 0;
+    }
   }
-}
 } // namespace Audio

+ 1 - 1
src/AudioPlayer.h

@@ -20,7 +20,7 @@ private:
   bool m_is_playing = false;
 
   float const m_frequency = 440.0f;
-  float const m_sample_rate = 44100.00f;
+  float const m_sample_rate = 48000.00f;
   float const m_amplitude = 1.0f;
   float m_phase = 0.0f;
 

+ 3 - 1
src/CMakeLists.txt

@@ -9,7 +9,9 @@ add_executable(audio-player
 
 
 
-       target_link_libraries(audio-player
+target_link_libraries(audio-player
                              spdlog)
 
 target_include_directories(audio-player PUBLIC ${CMAKE_SOURCE_DIR}/spdlog/include)
+
+set_target_properties(audio-player PROPERTIES CXX_STANDARD 17 CXX_EXTENSIONS OFF)

+ 4 - 4
src/main.cpp

@@ -18,14 +18,14 @@ int main () {
     Audio::AudioPlayer *m = new Audio::AudioPlayer();
     m->play();
     
-    if (m->is_playing()) {
+    /*if (m->is_playing()) {
         spdlog::info("Player is on play mode");
     } else {
         spdlog::info("Player is on pause mode");
-    }
+    }*/
 
-    //bodge: stop the program execution.
-    getchar();
+    system("pause");
+    
 
 
     m->pause();