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

Author Topic: Finished Sound Leaves Remaining 16k Tone, If 'stop' or 'getStatus' Not Called  (Read 5450 times)

0 Members and 5 Guests are viewing this topic.

Ezekiel

  • Newbie
  • *
  • Posts: 23
    • View Profile
Greetings All:

I noticed something that seems strange.  As mentioned on the Subject, I have been using the SFML Audio Module, and when a tone is finished, it leaves a remaining 16kHz tone.  View what I have seen in the attachment I made, and yes I didn't hear that myself, the testing equipment is necessary, well I only hear about to 12kHz.

I have done some exploring and found out the remaining tone is dependent to the final ~125 samples in the buffer, if the last samples are filled with zeros, it no longer shows up.  I have tried several sample-rate configurations, and it works similar using 96kHz, 48kHz and 22050Hz.  It's strange, 22050Hz doesn't have any range in the 16kHz position.  The volume was lower in the 96kHz rate, and the highest in the 22050Hz rate.  And if I call the 'stop' (playing or finished already), or the 'getStatus' functions, it goes away.  Closing the program also stop it.

I'm currently using SFML-2.3, I haven't updated to see if new version has changed this, but it doesn't appear that any mods in the last 2 revisions has changed anything applicable to that specific issue.  I'm using Windows 7 and have an X-Fi Creative Sound Blaster, if that changes anything.

Has anyone else seen that, or is it specific to my hardware?

I hope this is found interesting.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10987
    • View Profile
    • development blog
    • Email
And what are you doing code wise?
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Ezekiel

  • Newbie
  • *
  • Posts: 23
    • View Profile
Greetings All

Here are the few sections with the code...

In my Main Loop:
                //wait for key here
                rx_char = _getch();
                //clear 'Running' if has stopped
                if(SoundPlayer.getStatus() ==  sf::SoundSource::Status::Stopped)Running = false;
 

...other than above, if pressing the <space> bar, it calls "PlaySentence()"...
void sentence::PlaySentence()
{
        if(Running == false)
        {
                //play sentence HERE!!!
                RunSequence();//generates audio samples, stored in "SentenceSamples"
                //SentenceSamples is a "vector<sf::Int16>"

                if(SentanceSamples.size() >= 100)//skip if very few samples
                {
                        SentenceSound.loadFromSamples(&SentanceSamples[0], SentanceSamples.size(), 1, SampleRate);

                        SoundPlayer.setBuffer(SentenceSound);
                        SoundPlayer.setLoop(false);
                        SoundPlayer.play();

                        Running = true;
                }
        }
        else//Running?
        {
                //STOP PLAYING HERE
                SoundPlayer.stop();
                Running = false;
        }

}
 

The only other SF code references are the three items, Sound, SoundBuffer, and vector<sf::Int16>, declaried in the header.

The "RunSequence()" generates the samples.  I started using a sine wave, and changed to random sound to check if the 16kHz tone response changed.  When I used the sine, as I changed the number of zeros in the end of sample list, it ran into nodes that show no tone, until passed.

As I mentioned, if I pressed anything when the 16k tone is playing, the command loop called getStatus(), which would stop it.  And if <space> pressed when the generated sound, it would call stop(), which also stop the generated sound, and not leave the 16k tone.

I hope provides enough information, extracting the rest to generate the samples I have would fill many pages.  The small shown should work in a small main function if testing is planned.  Be sure using something visual, such as "VisualAnalyzer" as shown in the attached picture, unless your ears are better than mine.

I hope all find this interesting.

Ezekiel

  • Newbie
  • *
  • Posts: 23
    • View Profile
Greetings All:

I put together a simple program to demo the remaining tone I previously mentioned.  The program allows a different number of zeros left at the end of sample sequence.  Using the sine wave, it fades away with around ~100 samples zeroed at the end.  The remnant is larger of course, when you have 0 samples zeroed.  I used a static keeping track of the sine position used, so the sine wave won't end in the same position each time played, unless the time is a multiple cycle period, so the level change each time the <space> is pressed.  Calling stop() or getStatus() can be performed, and on my computer, both stops the 16k tone.

I hope this helps, the code follows...
// Remaining16kToneDemo.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"

#define _USE_MATH_DEFINES
#include <cmath>

#include <iostream>

#include <stdio.h>
#include <stdlib.h>
#include <vector>

#include <conio.h>
#include <windows.h>

#include <sfml.h>

using namespace std;

//globals
//configs
int SampleRate = 22050;
double ToneFrequency = 1000.1;
double ToneTime = 1.25;
int SamplesZeroAtEnd = 20;
//used as static, or accessed by functions
int CurrentSample = 0;
unsigned int SamplesNeeded =(unsigned int)(ToneTime * (double)SampleRate);
vector<sf::Int16> SentanceSamples;

//function headers
void RunSequence();
void PlaySentence();
int NumberKey(char value);//returns value, -1 if canceled



int _tmain(int argc, _TCHAR* argv[])
{

        sf::Sound SoundPlayer;
        sf::SoundBuffer SentenceSound;
        bool Running = false;

        //main loop
        for(unsigned char rx_char = 0x00; (rx_char != 27);)//escape exits
        {
                //display commands
                system("cls");

                cout << "<Numbers>\t\t: Set Value\n";
                cout << "<Space>\t\t\t: Play or Stop (If Still Playing)\n";
                cout << "'S'\t\t\t: Calls stop()\n";
                cout << "'G'\t\t\t: Calls getStatus()\n";
                cout << "<Esc>\t\t\t: Exits Program\n";

                cout << "\n";
                cout << "Samples Zero at the End\t: " << SamplesZeroAtEnd << "\n";

                //wait for key here
                rx_char = _getch();

                switch(rx_char)
                {
                        case 27://escape
                                break;
                        case 'S':
                        case 's':
                                SoundPlayer.stop();
                                break;
                        case 'G':
                        case 'g':
                                SoundPlayer.getStatus();
                                break;
                        case ' '://<space>
                                //clear 'Running' if has stopped
                                if(SoundPlayer.getStatus() ==  sf::SoundSource::Status::Stopped)Running = false;

                                if(Running == false)
                                {
                                        //play sentence HERE!!!
                                        RunSequence();//generates audio samples, stored in "SentenceSamples"
                                        //SentenceSamples is a "vector<sf::Int16>"

                                        if(SentanceSamples.size() >= 100)//skip if very few samples
                                        {
                                                SentenceSound.loadFromSamples(&SentanceSamples[0], SentanceSamples.size(), 1, SampleRate);

                                                SoundPlayer.setBuffer(SentenceSound);
                                                SoundPlayer.setLoop(false);
                                                SoundPlayer.play();

                                                Running = true;
                                        }
                                }
                                else//Running?
                                {
                                        //stop playing
                                        SoundPlayer.stop();
                                        Running = false;
                                }
                                break;
                        default:
                                //numbers
                                if(rx_char >= '0' && rx_char <= '9')
                                {
                                        SamplesZeroAtEnd = NumberKey(rx_char);
                                }
                }
        }
       
        return 0;
}

//functions
void RunSequence()
{
        SentanceSamples.resize(SamplesNeeded);
        unsigned int peak = ((1 << 15) - 1);
        double RadiansPerSample = 2.0 * M_PI * ToneFrequency / SampleRate;

        for(unsigned int i = 0;i < SamplesNeeded;i++)
        {
                SentanceSamples[i] = (unsigned int)round(sin((double)CurrentSample * RadiansPerSample) * (double)peak);
                CurrentSample++;
        }
        //change last sample to zero
        for(int i = 1;i <= SamplesZeroAtEnd;i++)
        {
                SentanceSamples[SentanceSamples.size() - i] = 0;
        }
}

int NumberKey(char value)
{
        int number = value - '0';
        cout << value;

        for(char rx_char = 0;;)
        {
                rx_char = _getch();
                if(rx_char >= '0' && rx_char <= '9')
                {
                        cout << rx_char;
                        number = number * 10 + rx_char - '0';
                }
                else if(rx_char == 13)//enter
                {
                        if(number > SamplesNeeded)return SamplesNeeded;
                        return number;
                }
                else if(rx_char == 8)//backspace
                {
                        if(number)
                        {
                                cout << "\b \b";
                                number = number / 10;
                        }
                }
        }
}
 

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10987
    • View Profile
    • development blog
    • Email
So I tested your code and don't really know what should go wrong.

When I press the space bar I get a sine wave and when I press the space bar again, it will stop. And it will also stop by pressing S. I never hear (or see) any weird 16k tone, but then again maybe I'm missing something here...




Oh yeah, since you used some weird Visual Studio only pieces and a missing header, here's code that should compile with other compilers as well.

(click to show/hide)
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
When I press the space bar I get a sine wave and when I press the space bar again, it will stop. And it will also stop by pressing S. I never hear (or see) any weird 16k tone, but then again maybe I'm missing something here...
Ezekiel seems to be suggesting that the tone appears when the sound has stopped - not playing - but only automatically, not manually.

Ezekiel, how are you finding evidence of this tone? Internal code, external software, or hardware?
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

Ezekiel

  • Newbie
  • *
  • Posts: 23
    • View Profile
Greetings eXpl0it3r:

I thought about the difference #including SFML modules after I posted it, I hope you've made it easier for others if they want to try it.  I used something that's posted in my previous subject quite a while ago, and it had to be changed with the newer releases as well.

For the remaining 16k tone to be created, press the <space> command, and let the 1.25 second sine wave finish (not stopped by command), and then it put's out the tone, which appears as a triangle with clipped top and bottom, until the program is stopped, or the stop() or getStatus() commands are sent.

I forgot to mention a few things...

Using the sine wave brings a much smaller tone, rather than using the obnoxious random square wave I used to generate the picture I posted.  The sin on my test program shows the 1000.1k tone as ~-10dB, and the 16k tone left behind is at ~-55dB, or smaller and changes every time the key is pressed.  This means it's about ~175 times smaller, or even less.  An analyzer using the FFT like I showed would help, searching for the title "Visual Analyzer" will Google that if interested.  To see a recording as you showed, turn the volume up ~200 times, and look at the line after the sine is finished.

My audio hardware is set up to 96kHz, so the 16k tone as my analyzer checks uses 6 samples repeating over and over, so increase the horizontal range as well.  If your hardware is set to 48k sample rate, the 16k would be 3 samples repeating, or may response differently, i.e. 8k with 6 samples.  And yes, the tone I see could just be something to do with my hardware, however the "getStatus()" shouldn't alter the hardware.

I hope that provides some more required information.  I may have some more test to do myself.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10987
    • View Profile
    • development blog
    • Email
I suspect that the issues is either related to your driver or to the way your audio things are setup. As you can see on the screens above and blow, there's literally nothing after the sine wave. No 16k tone, nothing. Additionally I can't hear anything.



I've used VB-Audio Voicemeeter to reroute the audio so I can directly record it in Audacity. But even if I use my headset or my speakers, I can't make out any repeating sound.

Can you hear the sound by itself? What did you use to "track" it down?
Is your audio driver installed and uptodate? What's your audio device?
Do you use the OpenAL that comes with SFML? Do you get any warnings or similar printed to the console?
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Ezekiel

  • Newbie
  • *
  • Posts: 23
    • View Profile
Greetings eXpl0it3r:

I first saw the tone on the Visual Analyzer, as I showed already.  I also saw a few level indicator lights on my external mixer, where I send the PC audio to directly.  And no, I never heard it.  I just did a hearing test, running my analog sine HP 204C Oscillator device (10Hz to 1MHz) to my mixer and turn it up (all level indicator lights on), I can only hear up to ~14kHz.

My initial idea was when "loop=false" and it plays to the end, it continue loops, but is pointing the the final sample.  However, changing the final sample to zero did nothing, but worked at >124 samples to zero, and reduces the level as approaching.  As a guess, that means the same "loop pointing at the last sample" is happening, but after the sample rate conversion.

For conversion i.e. 24000Hz to 96000 there are a few steps.  Convert up-sample-rate to match, "sample, 0, 0, 0", increase level *4 (compensate for zeros), filter out anything above 12kHz (i.e. 256-bit software FIR filter), send higher-frequency-samples (4*original) to sound-card or Windows control.

The 124 zero samples needed seems to indicate the "loop pointing at the last sample" happens at the post-up-sample point after a normal 256-bit FIR filter.

In the old days, a sound-card only allowed 1 program to use it at a time (Win95 and earlier), and now Windows hold all the keys, so any audio needs to be passed to using its format, which means converted by software beforehand.

So I think from what I saw, the tone is produced by the "loop pointing at the last sample", post-conversion by software, and then sent to Windows.  I checked out the 'sound.cpp' file, and it appears any issue, if it exists (but my hardware), is mostly in "openal32.lib", as it seems "sound.cpp" behaves as a wrapper, particularly of the functions posted in the demo-code I posted.

I tried adjusting the Playback-Device Sample Rate under Windows and it changed nothing.  And I previously did the demo code test using 22050Hz, which has the audio range up to half that, 11025Hz.  My sound-card claims it uses up to 192kHz on Playback, so everything prior to Windows7, or within Windows7 its self, is up-converted to that.

Below, I posted my Sound Card driver, if that helps...

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10987
    • View Profile
    • development blog
    • Email
I honestly didn't really understand what you were trying to tell/explain.
However did I correctly understand that you think this is not really caused by SFML?

Since you mentioned two different cards, do they create the same issue?
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Ezekiel

  • Newbie
  • *
  • Posts: 23
    • View Profile
Greetings eXpl0it3r:

Indeed, unless I'm missing something, SFML appears as a wrapper for OpenAL, at least for the few functions called as mentioned.  So the issue most likely occurs in the OpenAL=>Windows7=>Driver=>Sound-Card path, and if any step differs (i.e. OS or hardware), the result may be different.

I'm more of an electronic hardware person, and fit the Newbie title I have posted currently, so as far I have looked is in the Sound class forwarding the data to OpenAL class.  The sound-card's hardware interface details are not posted, and if anyone else know more about the OpenAL=>Windows7=>Driver section, that may help finding out what causes it.  With secrets under the hood in the path shown, some suspicions I mentioned may be different in reality.

Unless someone else can verify what experienced, it may not be excepted as a proven issue.  And even if so, it may be posted as unsolved.

Let me know if there's ever a newer OpenAl version sent with a newer release than SFML-2.3