Hello. I've been playing around with audio recently, specifically trying to code a simple synthesizer. It works fine when only unchanging (static) frequencies are used (see ex_synth), but as soon as I try to interpolate a frequency when generating the waveform, things go ... wonky.
Here's the clearest explanation of the problem that I know how to give: the program generates a waveform. The waveform should ramp smoothly from a lower frequency to a higher frequency, without detour. But instead, the waveform ramps too high (for reasons I can't even begin to guess at) before finally coming down to the target.
The code is a complete program that demonstrates the problem.
I've been banging my head on this for three days now ...
What could possibly be the problem?
I think it has to be something lying inside the types conversions. Have you enabled all the possible warnings to search and see ?
I would try to launch it in valgrind, to check for overflows.
Edit: I would also not use 'auto' and clearly choose a defined type instead.
Possibly you could try testing the code by replacing the interpolate function with a linear one. This should show if the input values you have at that point in your code are correct. Also, in your interpolate function try having a single point of return (i.e. first two return command could only set the temporary 'time' value for the final return to calculate the output).
Not really much help but who knows maybe it gives you some ideas as to what to try next.
You're interpolating from cos(0) to cos(PI). This means your wave is scaled by from 1 to 0 to -1 as it progresses. Try linear interpolation first, then mess with it.
I'm going to try your code and see if I can get it to work.
Replacing your interpolate function with a strict linear interpolation made the code work.
// Interpolate smoothly from 220 to 620 in 4 seconds. float wave = (220.0f + 100*ti) * pi2;
Ooh, try this :
float wave = (440.0f + 220.0f*(sin(pi2*(count + i)/(float)samples))/4.0f) * pi2;
I call it the SoundBlaster
Ouch, my ears! 
I've updated the program to address the remarks so far.
Regarding the use of auto and type conversions; trust me, if it was something simple like that I would have found it already. But anyway, all autos are replaced with concrete types. Also note, this program compiles without warnings using the usual flags: `-Wall -Weffc++ -Wextra -Wpedantic -Wconversion`.
I've added two new functions, linear interpolation and a function for discrete steps. The discrete step function produces the expected results as long as the step count is relatively low. Try making the step count 500 or higher; you'll start to notice the frequencies going too high.
I've added a command-line switch so you can test the different functions easily.
Edgar Reynaldo, I added your linear interpolate function, it's different from mine in that it doesn't have a specific target value, it just keeps increasing. Notice the problem shows up as soon as a target value is added to the code (command-line opt "edgar2").
The whole thing is very strange, I'm positive the problem can't be the interpolation function(s). 
Edit: try $program step 10000. The results are nearly the same as linear (i.e., wrong), ignoring the static effects.
I've tried the source as well. After changing it a little I managed to get it to work ok (?).
The problem seems to be with this line:
float va = std::sin(wave * ti);
In the below source, you will see that there is a new global variable called 'sine' which progresses with each generated sample and according to the frequency calculated in the interpolate function.
I'm not sure how to post the source code so sorry for this:
Marked with '// THIS IS NEW' are the changes I did:
#include <cstdint>
#include <cstddef>
#include <cstdlib>
#include <cassert>
#include <cstdio>
#include <cmath>
#include <allegro5/allegro.h>
#include <allegro5/allegro_audio.h>
float sine; // THIS IS NEW
// Interpolates from one frequency to another within a duration.
float interpolate(float time, float base, float change, float duration)
{
assert(duration > 0.0);
auto pi = (float)ALLEGRO_PI;
if (time <= 0.0) return base;
if (time >= duration) return base + change;
return -change / 2.0f * (std::cos(pi * time / duration) - 1.0f) + base;
}
// Generates the waveform.
void waveform(
float* buffer, int32_t samples, float time, uint64_t count, float vfreq)
{
auto pi = (float)ALLEGRO_PI;
auto pi2 = pi * 2.0f;
auto dt = 1.0f / vfreq;
for (int32_t i = 0; i < samples; ++i) {
float pt = (float)i;
float ti = time + pt * dt;
// Interpolate smoothly from 220 to 620 in 4 seconds.
float frequency = interpolate(ti, 220.0f, 400.0f, 4.0f) *pi2;
sine += frequency/44100.0f; // THIS IS NEW
float va = std::sin(sine);
buffer[i] = va;
}
}
int32_t main(int32_t, const char**)
{
sine = 0.0f; // THIS IS NEW
// Declare variables in advance because using 'goto' for cleanup.
bool success = false;
...
IT WORKS!
Thanks MikiZX, I can definitely say that your solution would never have occurred to me.
One thing about it that concerned me though, was that your sine variable would saturate eventually if the playback went on long enough. I fixed this with this code:
while(g_sine > pi2) g_sine -= pi2;
Here's the whole program, working correctly now. If anyone can think of a use for it, have at it!
One thing of note is that Edgar Reynaldo's SoundBlaster no longer sounds as it was originally intended to sound. I guess it depended on the wrong frequency behavior. 
Now if only I understood WHY it works ... I've been coding for years and I'm still not that good with math.
One thing that's helping for sure: always make the maximum number of operations before dividing.
a = ( b + c ) / d will keep precision longer than a = b/d + c/d
The sine thing look like a variable range problem. MikiZX added a global sine value which he initialize on main, and then iterate before using it along interpolation.
Hey, I thought you would be interested. I made a simple sound generator you might like.
Source code included (depends on Eagle and Allegro 5)