Recursive audio solution - c

I just want to get my head wrapped around recursion using something simple. I want amplitudes from 1 to -1. This will take less than two minutes.
I just through together a recursive solution to practice recursing.
/* This program outputs amplitudes within a frequency of 440Hz.
The number of audio samples will add of up to 1024, and the highest frequency
We can generate is about 20KilHz.
*/
#include<stdio.h>
#include<math.h>
#define PI 3.141597
#define TwoPI (2*3.141597)
#define SampleRate 441000
#define Frequency 440
#define Buffer 1024
/* Recursively Generates Signal, it is called in main. */
/*int CalculateSignal(int Sampler){
Sampler=0;
int Sample= 0;
Sample=sin(Frequency*TwoPI*SampleRate);
printf("%.6f",Sample);
if(Sampler==Buffer){
return Sample;
}
else if(Sampler<Buffer){
return CalculateSignal(Sampler+1);
}
}*/
int main(){
CalculateSignal(1024);
}

Related

FFT with dsPIC33E returns no frequency

I'm working with a dsPIC33EP128GP502 and try to run a FFT to measure the dominant frequency on the input. The compiler shows no errors and the ADC itself seems to work... (for single values)
I expect as result some frequency value between 0 Hz and ~96 kHz in the variable peakFrequency. With a noise signal (or no signal at all) the value should be more or less random. With an external applied single tone signal I expect to measure the input frequency +/- ~100 Hz. Sadly, my frequency output is always 0.
The test signals are generated by external signal generators and the ADC works fine if I want to measure single values!
The FFT has to run on the DSP-core of the dsPIC33E due to some performance needs.
Has anyone any experience with the dsPIC33E and an idea were my mistake is?
ADC: TAD -> 629.3 ns, Conversion Trigger -> Clearing sample bit ends sampling and starts conversion, Output Format -> Fractional result, signed, Auto Sampling -> enabled
#include "mcc_generated_files/mcc.h"
#include <xc.h>
#include <dsp.h>
#define FFT_BLOCK_LENGTH 1024
#define LOG2_BLOCK_LENGTH 10
#define AUDIO_FS 192042
int16_t peakFrequencyBin;
uint16_t ix_MicADCbuff;
uint16_t peakFrequency;
fractional fftMaxValue;
fractcomplex twiddleFactors[FFT_BLOCK_LENGTH/2] __attribute__ ((space(xmemory)));
fractcomplex sigCmpx[FFT_BLOCK_LENGTH] __attribute__ ((space(ymemory), aligned(FFT_BLOCK_LENGTH * 2 *2)));
bool timeGetAdcSample = false;
void My_ADC_IRS(void)
{
timeGetAdcSample = true;
}
void readOutput(void)//Sample output
{
for(ix_MicADCbuff=0;ix_MicADCbuff<FFT_BLOCK_LENGTH;ix_MicADCbuff++)
{
ADC1_ChannelSelect(mix_output);
ADC1_SoftwareTriggerEnable();
while(!timeGetAdcSample); //wait for TMR1 interrupt (5.2072 us)
timeGetAdcSample = false;
ADC1_SoftwareTriggerDisable();
while(!ADC1_IsConversionComplete(mix_output));
sigCmpx[ix_MicADCbuff].real = ADC1_Channel0ConversionResultGet();
sigCmpx[ix_MicADCbuff].imag = 0;
}
}
void signalFreq(void)//Detect the dominant frequency
{
readOutput();
FFTComplexIP(LOG2_BLOCK_LENGTH, &sigCmpx[0], &twiddleFactors[0], COEFFS_IN_DATA);/
BitReverseComplex(LOG2_BLOCK_LENGTH, &sigCmpx[0]);
SquareMagnitudeCplx(FFT_BLOCK_LENGTH, &sigCmpx[0], &sigCmpx[0].real);
VectorMax(FFT_BLOCK_LENGTH/2, &sigCmpx[0].real, &peakFrequencyBin);
peakFrequency = peakFrequencyBin*(AUDIO_FS/FFT_BLOCK_LENGTH);
}
int main(void)
{
SYSTEM_Initialize();
TwidFactorInit(LOG2_BLOCK_LENGTH, &twiddleFactors[0], 0);
TMR1_SetInterruptHandler(My_ADC_IRS);
TMR1_Start();
while (1)
{
signalFreq();
UART1_32_Write((uint32_T)peakFrequency); // output via UART
}
return 1;
}
Perhaps anyone can figure out the error/problem in my code!

Why does my audio output increase of 100Hz on each cycle?

I have a bug in my audio code.
Expected behavior: sinewave output, sweeping from 100Hz to 200Hz, resetting to 100Hz every second
Actual behavior: sinewave output, sweeping from 100Hz to 200Hz, but then rising 100Hz on each cycle, so on the second cycle it will sweep from 200Hz to 300Hz, then from 300Hz to 400Hz, and so on...
I'm generating a 1Hz rising sawtooth wave, and scaling and offsetting it so it rises from 100 to 200 every second. I'm also printing its value, which shows that it's behaving as expected.
But for some reason, if I use that value as frequency for my sinewave, the resulting sound rises 100Hz on each cycle.
Plugging a fixed frequency into my sinewave function works as expected.
It's only when I use the two together that I'm getting the bug. The thing I really can't explain is that the bug is only in the output audio -- the printed values are still all fine.
I'm using miniaudio as audio backend, and it's the only dependency. It should compile without errors nor warnings on Win, Linux and Mac.
It's a single header library, you only need to include miniaudio.h, so it should be easy to replicate.
Here is my code:
/*
compiling on Win10 with GCC:
gcc -g0 test_nodep.c -o test_nodep.exe -Wall -Wextra -Wshadow -Wvla -pedantic-errors -ansi
*/
#include <stdio.h>
#include <math.h>
#include <float.h>
#include <stdint.h>
#define MA_NO_DECODING
#define MA_NO_ENCODING
#define MINIAUDIO_IMPLEMENTATION
#include "miniaudio.h" /* https://github.com/mackron/miniaudio - single header file audio os backend library */
/* global variables */
int32_t DEVICE_FORMAT = ma_format_f32; /* 32-bit float */
int32_t DEVICE_CHANNELS = 1; /* mono */
int32_t DEVICE_SAMPLE_RATE = 48000;
float clock = 0;
float time = 0;
static __inline__ float tik(float interval, float len, float offset){
return (len<=0)*(fmod(time-offset, interval)==0) +
(len>0)*((fmod(time-offset, interval)>=0)&&(fmod(time-offset, interval)<=(len)));
}
void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount){
float* Samples = pOutput;
ma_uint32 SampleIndex;
/* audio-callback variable definitions */
float test_saw;
float test_saw_freq = 1.f;
float i;
for(SampleIndex = 0; SampleIndex < frameCount; SampleIndex++){
test_saw = fmod(clock, (DEVICE_SAMPLE_RATE/test_saw_freq))/(DEVICE_SAMPLE_RATE/test_saw_freq); /* 1Hz rising saw, output range [0..1] */
test_saw = test_saw * 100.f + 100.f; /* shift range into [100..200] */
if(tik(.125f,0.f,0.f)){ /* this is to print the test_saw value every 1/8 of a second */
printf("== test_saw: %.2f", test_saw);
for(i=0.f;i<test_saw/10.f;i++){
printf(" ");
}
printf("%c\n", 254);
}
/* this is the output function, a sinewave, with frequency sweeping continuously from 100Hz to 200Hz */
/* f(t) = sin(2*PI * frequency + time) */
/* instead of a fixed frequency, I'm using test_saw, sweeping from 100Hz to 200Hz every second */
*Samples = (float)sin((double)(time * MA_TAU * test_saw));
/* using the same function with a fixed frequency works as expected, no problems */
/* *Samples = (float)sin((double)(time * MA_TAU * 100.f)); */
clock++;
clock*=(clock<FLT_MAX); /* continuously rising value, +1 on each sample, zeroes out when float is at its max value, to prevent float overflow */
time = clock/DEVICE_SAMPLE_RATE; /* same value, in seconds */
Samples++;
}
(void)pDevice;
(void)pInput;
}
int main(){
ma_device_config deviceConfig;
ma_device device;
/* audio output device configuration */
deviceConfig = ma_device_config_init(ma_device_type_playback); /* initialize for playback */
deviceConfig.playback.format = DEVICE_FORMAT;
deviceConfig.playback.channels = DEVICE_CHANNELS;
deviceConfig.sampleRate = DEVICE_SAMPLE_RATE;
deviceConfig.dataCallback = data_callback;
/* audio output device initialization */
if(ma_device_init(NULL, &deviceConfig, &device) != MA_SUCCESS){
printf("Failed to open playback device.\n");
return -4;
}
printf("== Device Name: %s\n", device.playback.name);
printf("== Sample Rate: %u Hz\n", DEVICE_SAMPLE_RATE);
if (ma_device_start(&device) != MA_SUCCESS) {
printf("== Failed to start playback device.\n");
ma_device_uninit(&device);
return -5;
}
printf("~~~ You should hear sound now ~~~\n");
printf("== Press Enter to quit...");
getchar();
ma_device_uninit(&device); /* turn off sound */
return 0;
}

7 Segment Rfid Counter

I have rfid circuits. Im trying to add a counter with a 7 seven segment.
My seven segment giving random numbers like this.Photo
I think these numbers are opposite of my numbers. How can i solve this problem?
#include <16F887.h>
#fuses XT,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,NOPUT,NOWRT,NODEBUG,NOCPD
#use delay(clock=4m,oscillator)
#define Dig1 PIN_D0
#define Dig2 PIN_D1
#define rfid PIN_D2
#define reset PIN_A1
#use fast_io(b)
#use fast_io(d)
char birler = 0, onlar = 0, sayi = 0;
void main()
{
int digit[10]={0b0111111,0b0000110,0b1011011,0b1001111,0b1101101,0b1111101,0b0000111,0b1111111,0b1101111};
set_tris_b(0x00);
output_b(1);
set_tris_d(0b11111100);
output_d(0b11111100);
output_b(0b11111100);
while(1)
{
output_b(digit[onlar]);
output_d(0b11111101);
delay_ms(5);
output_b(digit[birler]);
output_d(0b11111110);
delay_ms(5);
if(input(rfid) == 0)
{
sayi++;
birler = sayi%10;
onlar = sayi/10;
while(input(rfid) == 0)
{
output_b(digit[onlar]);
output_d(0b11111101);
delay_ms(5);
output_b(digit[birler]);
output_d(0b11111110);
delay_ms(5);
}
}
}
}
You really should consider isolating the display from your main loop, and eliminating the inline delays in your code. Pros are increased readability, easier maintenance, and eliminating delays for doing the actual work.
While preparing this response, I found out that your segments table is missing entries. Entry for '4' is missing.
The code below is far from complete. There is a digit missing in the LED segments table, you're using a switch that needs debouncing and it lacks a clock for non-blocking timers.
I've copy/pasted much of your app, and added comments...
#include <16F887.h>
#fuses XT,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,NOPUT,NOWRT,NODEBUG,NOCPD
#use delay(clock=4m,oscillator)
#define Dig1 PIN_D0
#define Dig2 PIN_D1
#define rfid PIN_D2
#define reset PIN_A1
#use fast_io(b)
#use fast_io(d)
// never define const arrays on the stack.
static const int digit[10]= { 0b0111111, 0b0000110, 0b1011011, 0b1001111, /* missing '4' */ 0,
0b1101101, 0b1111101, 0b0000111, 0b1111111, 0b1101111 };
void display(unsigned char value)
{
static char tens = 0;
char dig = (tens) ? (value / 10) : (value % 10);
dig = digit[dig];
output_high((tens} ? Dig2 : Dig1);
output_b(dig); // <-- clobbers the high bit of B
output_low((tens} ? Dig1 : Dig2); // preventing other uses for it.
tens = !tens;
}
void main()
{
char sayi = 0;
output_b(1);
output_d(0b11111100);
output_b(0b11111100); // why set PORTB to 1 earlier? is that a bug?
set_tris_b(0x00); // always init tristate AFTER setting output
set_tris_d(0b11111100);
while(1)
{
display(sayi);
if(input(rfid) == 0) // debouncing needed. 30ms is a good delay for debouncing
{
sayi++; // what happens when we reach 100 ???
}
delay_ms(30); // in real-life, this should not be there.
// there are better ways to throttle a program,
// including going to sleep/idle.
}
}
I think these numbers are opposite of my numbers.
Check if your seven segment is common cathode or not, as it seems that the code is built for common cathode seven segment
And if it is common anode and it is your only choice, you can simply change the code to fit it by toggling all the bits in digit array, for ex zero will be 0b10000000
If your numbers are not appearing correctly, consider changing the digit array to
digit[] = {0b1, 0b10, 0b100, 0b1000, 0b10000, 0b100000, 0b1000000};
and run each pattern for 5 seconds. That will tell you which bit is controlling which segment. What I've noticed about 7-segment displays from different manufacturers is that they don't always number the segments in the same way so 0b111111 may appear as 6 or 9: not necessarily 0.

How to measure the elapsead time below nanosecond for x86?

I have searched and used many approaches for measuring the elapsed time. there are many questions for this purpose. For example, this question is very good but when you need an accurate time recorder I couldn't find a good method. For this, I want to share my method here to be used and be corrected if something is wrong.
UPDATE&NOTE: this question is for Benchmarking, less than one nanosecond. It's completely different from using clock_gettime(CLOCK_MONOTONIC,&start); it records time more than one nanosecond.
UPDATE : A common method to measure the speedup is repeating a section of the program which should be benchmarked. But, as mentioned in comment it might show different optimization when the researcher rely on autovectorizing.
NOTE It's not accurate enough to measure the elapsed time in one repeatinng. In some cases my results show that the section must be repeated more than 1K or 1M to get the smallest time.
SUGGESTION : I'm not familiar with shell programming (just know some basic commands...) But, it might be possible to measure the smallest time with out repeating inside the program.
MY CURRENT SOLUTION In order to prevent the branches I repeat the ode section using a macro #define REP_CODE(X) X X X... X X which X is the code section I want to benchmark as follows:
//numbers
#define FMAX1 MAX1*MAX1
#define COEFF 8
int __attribute__(( aligned(32))) input[FMAX1+COEFF]; //= {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17};
int __attribute__(( aligned(32))) output[FMAX1];
int __attribute__(( aligned(32))) coeff[COEFF] = {1,2,3,4,5,6,7,8};//= {1,1,1,1,1,1,1,1};//; //= {1,2,1,2,1,2,1,2,2,1};
int main()
{
REP_CODE(
t1_rdtsc=_rdtsc();
//Code
for(i = 0; i < FMAX1; i++){
for(j = 0; j < COEFF; j++){//IACA_START
output[i] += coeff[j] * input[i+j];
}//IACA_END
}
t2_rdtsc=_rdtsc();
ttotal_rdtsc[ii++]=t2_rdtsc-t1_rdtsc;
)
// The smallest element in `ttotal_rdtsc` is the answer
}
This does not impact the optimization but also is restricted by code size and compiling time is too much in some cases.
Any suggestion and correction?
Thanks in advance.
If you have problem with autovectorizer and want to limit it just add a asm("#somthing"); after your begin_rdtsc it will separate the do-while loop. I just checked and it vectorized your posted code which auto vectorizer was unable to vectorize it.
I changed your macro you can use it....
long long t1_rdtsc, t2_rdtsc, ttotal_rdtsc[do_while], ttbest_rdtsc = 99999999999999999, elapsed, elapsed_rdtsc=do_while, overal_time = OVERAL_TIME, ttime=0;
int ii=0;
#define begin_rdtsc\
do{\
asm("#mmmmmmmmmmm");\
t1_rdtsc=_rdtsc();
#define end_rdtsc\
t2_rdtsc=_rdtsc();\
asm("#mmmmmmmmmmm");\
ttotal_rdtsc[ii]=t2_rdtsc-t1_rdtsc;\
}while (ii++<do_while);\
for(ii=0; ii<do_while; ii++){\
if (ttotal_rdtsc[ii]<ttbest_rdtsc){\
ttbest_rdtsc = ttotal_rdtsc[ii];}}\
printf("\nthe best is %lld in %lld iteration\n", ttbest_rdtsc, elapsed_rdtsc);
I have developed my first answer and got this solution. But, I still want a solution. Because it is very important to measure the time accurately and with the least impacts. I put this part in a header file and include it in main program files.
//Header file header.h
#define count 1000 // number of repetition
long long t1_rdtsc, t2_rdtsc, ttotal_rdtsc[count], ttbest_rdtsc = 99999999999999999, elapsed, elapsed_rdtsc=count, overal_time = OVERAL_TIME, ttime=0;
int ii=0;
#define begin_rdtsc\
do{\
t1_rdtsc=_rdtsc();
#define end_rdtsc\
t2_rdtsc=_rdtsc();\
ttotal_rdtsc[ii]=t2_rdtsc-t1_rdtsc;\
}while (ii++<count);\
for(ii=0; ii<do_while; ii++){\
if (ttotal_rdtsc[ii]<ttbest_rdtsc){\
ttbest_rdtsc = ttotal_rdtsc[ii];}}\
printf("\nthe best is %lld in %lldth iteration \n", ttbest_rdtsc, elapsed_rdtsc);
//Main program
#include "header.h"
.
.
.
int main()
{
//before the section
begin_rdtsc
//put your code here to measure the clocks.
end_rdtsc
return 0
}
I recommend using this method for x86 micro-architecture.
NOTE:
NUM_LOOP should be a number which helps to increase the accuracy
with repeating your code to record the best time
ttbest_rdtsc must
be bigger than the worst time I recommend to maximize it.
I used (you might not want it) OVERAL_TIME as another checking rule because I used this for many kernels and in some cases NUM_LOOP was very big and I didn't want to change it. I planned OVERAL_TIME to limit the iterations and stop after specific time.
UPDATE: The whole program is this:
#include <stdio.h>
#include <x86intrin.h>
#define NUM_LOOP 100 //executes your code NUM_LOOP times to get the smalest time to avoid overheads such as cache misses, etc.
int main()
{
long long t1_rdtsc, t2_rdtsc, ttotal_rdtsc, ttbest_rdtsc = 99999999999999999;
int do_while = 0;
do{
t1_rdtsc = _rdtsc();
//put your code here
t2_rdtsc = _rdtsc();
ttotal_rdtsc = t2_rdtsc - t1_rdtsc;
//store the smalest time:
if (ttotal_rdtsc<ttbest_rdtsc)
ttbest_rdtsc = ttotal_rdtsc;
}while (do_while++ < NUM_LOOP);
printf("\nthe best is %lld in %d repetitions\n", ttbest_rdtsc, NUM_LOOP );
return 0;
}
that I have changed to this and added to a header for my self then I can use it simply in my program.
#include <x86intrin.h>
#define do_while NUM_LOOP
#define OVERAL_TIME 999999999
long long t1_rdtsc, t2_rdtsc, ttotal_rdtsc, ttbest_rdtsc = 99999999999999999, elapsed, elapsed_rdtsc=do_while, overal_time = OVERAL_TIME, ttime=0;
#define begin_rdtsc\
do{\
t1_rdtsc=_rdtsc();
#define end_rdtsc\
t2_rdtsc=_rdtsc();\
ttotal_rdtsc=t2_rdtsc-t1_rdtsc;\
if (ttotal_rdtsc<ttbest_rdtsc){\
ttbest_rdtsc = ttotal_rdtsc;\
elapsed=(do_while-elapsed_rdtsc);}\
ttime+=ttotal_rdtsc;\
}while (elapsed_rdtsc-- && (ttime<overal_time));\
printf("\nthe best is %lld in %lldth iteration and %lld repetitions\n", ttbest_rdtsc, elapsed, (do_while-elapsed_rdtsc));
How to use this method? Well, it is very simple!
int main()
{
//before the section
begin_rdtsc
//put your code here to measure the clocks.
end_rdtsc
return 0
}
Be creative, You can change it to measure the speedup in your program, etc.
An example of the output is:
the best is 9600 in 384751th iteration and 569179 repetitions
my tested code got 9600 clock that the best was recorded in 384751enditeration and my code was tested 569179 times
I have tested them on GCC and Clang.

Get average run-time of a C program

I'm trying to measure differences in speed of reading and writing misaligned vs aligned bits into binary files. I would like to know is there an utility I can use (Except for running time over & over again and writing my own) to sample an average run-time of a program (I'm running Linux based OS)?
Thanks
running time over & over again and writing my own
That's fine. You can perform the read/write ten thousand times both ways and compute the average time.
If you really want to use a library you can try Google Perftools.
Put this in a header file:
#ifndef TIMER_H
#define TIMER_H
#include <stdlib>
#include <sys/time.h>
typedef unsigned long long timestamp_t;
static timestamp_t
get_timestamp ()
{
struct timeval now;
gettimeofday (&now, NULL);
return now.tv_usec + (timestamp_t)now.tv_sec * 1000000;
}
#endif
Include the header file into whichever .c file you'll be using, and do something like this:
#define N 10000
int main()
{
int i;
double avg;
timestamp_t start, end;
start = get_timestamp();
for(i = 0; i < N; i++)
foo();
end = get_timestamp();
avg = (end - start) / (double)N;
printf("%f", avg);
return 0;
}
Basically this calls whichever function you're trying to measure performance of N times, where N is a defined constant (doesn't have to be) in this case. It takes a timestamp before the for loop and after the for loop and then calculates the average time it's taken for the function to execute. The get_timestamp() function returns the number of microseconds, so if you need milliseconds, divide by 1000, seconds - divide by 1000000 etc.

Resources