Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: How to get the current audio sample?  (Read 3398 times)

0 Members and 2 Guests are viewing this topic.

kirilzh

  • Newbie
  • *
  • Posts: 6
    • View Profile
    • Email
How to get the current audio sample?
« on: March 31, 2018, 02:10:28 pm »
I'm trying to apply a Fourier Transform on the current audio sample. This is how I'm accessing all samples and storing them in a variable.
const auto samples = buffer.getSamples();
To get the current playing position I'm using
sf::Sound::getPlayingOffset() const
because this is the closest thing I found to what I'm trying to achieve. However, I don't think it will work in my case because the only usage of this method I found is to return the seconds of playback that have elapsed.
  while (sound.getStatus() == sf::Sound::Playing){
    // Display the playing position
    std::cout << "\rPlaying... " << sound.getPlayingOffset().asSeconds() << " sec";
    std::cout << std::flush;
  }

My question is is there a way I can access only the current sample that is played and apply Fourier Transform to it. If yes which methods should I be looking at?

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: How to get the current audio sample?
« Reply #1 on: March 31, 2018, 02:27:27 pm »
getPlayingOffset returns an sf::Time. To get the currently playing sample from this, multiply the number of seconds by the sample frequency. To get the actual sample data, you'll also need to multiply the number of channels.
So, to get the memory for the currently-played sample, it would be something like (for a stereo sound):
// sound and soundBuffer need to already exist and be setup (and playing)
const unsigned int sampleFrequency{ 44100u };
const unsigned int numberOfChannels{ 2u };
const sf::Int16* sampleData{ soundBuffer.getSamples() };
const sf::Time currentPlayingTime{ sound.getPlayingOffset() };
const sf::Uint32 currentSamplePosition{ currentPlayingTime.asSeconds() * sampleFrequency };
const sf::Uint32 currentSampleDataIndex{ currentSamplePosition * numberOfChannels };
sf::Int16 leftChannel{ sampleData[currentSampleDataIndex] };
sf::Int16 rightChannel{ sampleData[currentSampleDataIndex + 1] };
A few important notes though:
1) this isn't mega accurate since the time multiplied is a float,
2) by the time time you do anything with this information, it's almost certain that some other part of the sound is now playing,
3) you can't actually alter a sound buffer so the sound can't be changed.

If you want to process a sound as it plays, you more than likely want to look at using sound streams instead. That way, you can process each chunk as they appear.
https://www.sfml-dev.org/tutorials/2.4/audio-streams.php
https://www.sfml-dev.org/documentation/2.4.2/classsf_1_1SoundStream.php
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

kirilzh

  • Newbie
  • *
  • Posts: 6
    • View Profile
    • Email
Re: How to get the current audio sample?
« Reply #2 on: March 31, 2018, 02:39:41 pm »
Thank you! When I think about it your answer makes a lot of sense. I'm new to SFML and C++ programming as a whole so I really appreciate you taking the time to explain what I was doing wrong. One last thing I want to ask is what is a good source to read more about signal processing and where did you start learning from?