Channel Frequency of 0 not Respected for Streams

Hi!

I continuously manipulate the frequency of a channel through game interaction but for some odd reason when I get close to and eventually precisely to 0 the actual frequency stays at 100.

I confirmed that I literally call setFrequency with a float value of 0 but if I query the value afterwards using getFrequency I get back 100.

I noticed that the problem only happens when I load the corresponding music via FMOD_CREATESTREAM. If I load it via FMOD_CREATESAMPLE the problem is not there.

The documentation says:

Sounds opened as FMOD_CREATESAMPLE (not FMOD_CREATESTREAM or FMOD_CREATECOMPRESSEDSAMPLE) can be played backwards by giving a negative frequency.

But 0 should work in both cases, shouldn’t it?

I use the latest FMOD 2.02 lib at 2.02.25.

Best regards,
Thomas

Hi,

Thank you for the information.

Unfortunately, I was not able to reproduce the issue.

Would it be possible to get a code snippet to test on my side?

I was able to reproduce the issue with the following minimal example. I use an OGG file as music input and compiled on macOS. If you want, I can upload a full compilable example to my profile.

#include <chrono>
#include <fmod/fmod.hpp>
#include <iostream>
#include <thread>

namespace {
constexpr int k_maxAudioChannels = 32;
constexpr float k_rateStep = 0.01F;
constexpr const char* k_path = "assets/music.ogg";
constexpr int k_sleepTimeMs = 20;
}  // namespace

int main(int argc, char** args) {
  // Startup
  FMOD::System* system_p = nullptr;
  FMOD::System_Create(&system_p);
  system_p->init(k_maxAudioChannels, FMOD_INIT_NORMAL, nullptr);

  FMOD::ChannelGroup* musicChannelGroup_p = nullptr;
  system_p->createChannelGroup("Music Channel Group", &musicChannelGroup_p);

  // Load music
  FMOD::Sound* sound_p = nullptr;
  system_p->createSound(k_path, FMOD_CREATESTREAM, nullptr, &sound_p);

  // Read default frequency
  float defaultFreq = 0.F;
  sound_p->getDefaults(&defaultFreq, nullptr);

  // Play music
  FMOD::Channel* channel_p = nullptr;
  system_p->playSound(sound_p, musicChannelGroup_p, false, &channel_p);

  // Main loop
  float playbackRate = 1.F;
  while (true) {
    float freq = 0.F;
    channel_p->getFrequency(&freq);
    std::cout << "Channel frequency: " << freq << std::endl;

    channel_p->setFrequency(defaultFreq * playbackRate);
    system_p->update();

    playbackRate = std::max(playbackRate - k_rateStep, 0.F);
    std::this_thread::sleep_for(std::chrono::milliseconds(k_sleepTimeMs));
  }

  // Shutdown
  musicChannelGroup_p->stop();

  if (sound_p) {
    sound_p->release();
    sound_p = nullptr;
  }

  if (musicChannelGroup_p) {
    musicChannelGroup_p->release();
    musicChannelGroup_p = nullptr;
  }

  if (system_p) {
    system_p->close();
    system_p->release();
    system_p = nullptr;
  }

  return 0;
}

This example leads to the following output:

Channel frequency: 44100
Channel frequency: 44100
Channel frequency: 43659
Channel frequency: 43218
Channel frequency: 42777
Channel frequency: 42336
Channel frequency: 41895
Channel frequency: 41454
Channel frequency: 41013
Channel frequency: 40572
Channel frequency: 40131
Channel frequency: 39690
Channel frequency: 39249
Channel frequency: 38808
Channel frequency: 38367
Channel frequency: 37926
Channel frequency: 37485
Channel frequency: 37044
Channel frequency: 36603
Channel frequency: 36162
Channel frequency: 35721
Channel frequency: 35280
Channel frequency: 34839
Channel frequency: 34398
Channel frequency: 33957
Channel frequency: 33516
Channel frequency: 33075
Channel frequency: 32634
Channel frequency: 32193
Channel frequency: 31752
Channel frequency: 31311
Channel frequency: 30870
Channel frequency: 30429
Channel frequency: 29988
Channel frequency: 29547
Channel frequency: 29106
Channel frequency: 28665
Channel frequency: 28224
Channel frequency: 27783
Channel frequency: 27342
Channel frequency: 26901
Channel frequency: 26460
Channel frequency: 26019
Channel frequency: 25578
Channel frequency: 25137
Channel frequency: 24696
Channel frequency: 24255
Channel frequency: 23814
Channel frequency: 23373
Channel frequency: 22932
Channel frequency: 22491
Channel frequency: 22050
Channel frequency: 21609
Channel frequency: 21168
Channel frequency: 20727
Channel frequency: 20286
Channel frequency: 19845
Channel frequency: 19404
Channel frequency: 18963
Channel frequency: 18522
Channel frequency: 18081
Channel frequency: 17640
Channel frequency: 17199
Channel frequency: 16758
Channel frequency: 16317
Channel frequency: 15876
Channel frequency: 15435
Channel frequency: 14994
Channel frequency: 14553
Channel frequency: 14112
Channel frequency: 13671
Channel frequency: 13230
Channel frequency: 12789
Channel frequency: 12348
Channel frequency: 11907
Channel frequency: 11466
Channel frequency: 11025
Channel frequency: 10584
Channel frequency: 10143
Channel frequency: 9702.03
Channel frequency: 9261.03
Channel frequency: 8820.03
Channel frequency: 8379.03
Channel frequency: 7938.03
Channel frequency: 7497.03
Channel frequency: 7056.03
Channel frequency: 6615.03
Channel frequency: 6174.03
Channel frequency: 5733.03
Channel frequency: 5292.03
Channel frequency: 4851.03
Channel frequency: 4410.03
Channel frequency: 3969.03
Channel frequency: 3528.03
Channel frequency: 3087.03
Channel frequency: 2646.03
Channel frequency: 2205.03
Channel frequency: 1764.03
Channel frequency: 1323.03
Channel frequency: 882.03
Channel frequency: 441.03
Channel frequency: 100
Channel frequency: 100
Channel frequency: 100
Channel frequency: 100
Channel frequency: 100
...

Thanks!

Thomas

FMOD currently have an internal minimum frequency for channels set at 100Hz, which is likely a holdover from FMOD adhering to older audio standards like DirectSound. Additionally, many hardware codecs have minimum playback frequency limits above 100Hz. There’s currently no way around this minimum.

There is the potential to push it lower in cases where it can be, and I’ve added this to our improvement tracker. I’ve also flagged info on the internal minimum frequency to be added the Channel::setFrequency docs entry.

Alright, thank you. Then I will most likely add a workaround that explicitly pauses the music when I have a playback rate of 0 and resumes it when it goes above 0 again.

1 Like