Create a twiddle table with a specific order? [closed] - c

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I was hoping to create a twiddle table with a specific ordering for a specific purpose, here is the initial code:
#define TWIDDLE_LIMIT 64
#define PI 3.1415927
float *twiddle_real;
float *twiddle_imag;
void main()
{
int N = 256;
int TW_size = TWIDDLE_LIMIT + (TWIDDLE_LIMIT>>2);
twiddle_real = malloc(TW_size * sizeof(float));
twiddle_imag = malloc(TW_size * sizeof(float));
int i;
for(i=0; i<TWIDDLE_LIMIT; i++)
{
twiddle_real[i] = (float) cos((float)i * 2.0 * PI / (float)N);
twiddle_imag[i] = (float) - sin((float)i * 2.0 * PI / (float)N);
}
for(int a=0; a<TWIDDLE_LIMIT; a++)
printf("RE = %f \t IM = %f \n",twiddle_real[a],twiddle_imag[a]);
}
And i get this kind of result:
RE = 1.000000 IM = -0.000000 //64 lines
RE = 0.999699 IM = -0.024541
RE = 0.998795 IM = -0.049068
RE = 0.997290 IM = -0.073565
RE = 0.995185 IM = -0.098017
RE = 0.992480 IM = -0.122411
RE = 0.989177 IM = -0.146730
RE = 0.985278 IM = -0.170962
RE = 0.980785 IM = -0.195090
RE = 0.975702 IM = -0.219101
RE = 0.970031 IM = -0.242980
RE = 0.963776 IM = -0.266713
RE = 0.956940 IM = -0.290285
RE = 0.949528 IM = -0.313682
RE = 0.941544 IM = -0.336890
RE = 0.932993 IM = -0.359895
RE = 0.923880 IM = -0.382683
RE = 0.914210 IM = -0.405241
RE = 0.903989 IM = -0.427555
RE = 0.893224 IM = -0.449611
RE = 0.881921 IM = -0.471397
RE = 0.870087 IM = -0.492898
RE = 0.857729 IM = -0.514103
RE = 0.844854 IM = -0.534998
RE = 0.831470 IM = -0.555570
RE = 0.817585 IM = -0.575808
RE = 0.803208 IM = -0.595699
RE = 0.788346 IM = -0.615232
RE = 0.773010 IM = -0.634393
RE = 0.757209 IM = -0.653173
RE = 0.740951 IM = -0.671559
RE = 0.724247 IM = -0.689541
RE = 0.707107 IM = -0.707107
RE = 0.689541 IM = -0.724247
RE = 0.671559 IM = -0.740951
RE = 0.653173 IM = -0.757209
RE = 0.634393 IM = -0.773010
RE = 0.615232 IM = -0.788346
RE = 0.595699 IM = -0.803208
RE = 0.575808 IM = -0.817585
RE = 0.555570 IM = -0.831470
RE = 0.534998 IM = -0.844854
RE = 0.514103 IM = -0.857729
RE = 0.492898 IM = -0.870087
RE = 0.471397 IM = -0.881921
RE = 0.449611 IM = -0.893224
RE = 0.427555 IM = -0.903989
RE = 0.405241 IM = -0.914210
RE = 0.382683 IM = -0.923880
RE = 0.359895 IM = -0.932993
RE = 0.336890 IM = -0.941544
RE = 0.313682 IM = -0.949528
RE = 0.290285 IM = -0.956940
RE = 0.266713 IM = -0.963776
RE = 0.242980 IM = -0.970031
RE = 0.219101 IM = -0.975702
RE = 0.195090 IM = -0.980785
RE = 0.170962 IM = -0.985278
RE = 0.146730 IM = -0.989177
RE = 0.122411 IM = -0.992480
RE = 0.098017 IM = -0.995185
RE = 0.073565 IM = -0.997290
RE = 0.049068 IM = -0.998795
RE = 0.024541 IM = -0.999699
And this is only a minimal exaple that I can explain you as much as possibble.
What i want and tried to create is a table that begins with the earlier set of lines and the resdt will be as following:
(earlier set of lines) expressed as following(idx:0 --- > 64)
re[idx] = (float) cos((float)i * (2*pi)/(float)N);
im[idx] = (float)-sin((float)i * (2*pi)/(float)N);
(2nd set of lines) expressed as following repeated 4 times consequently
re[idx] = (float) cos(4 * (float)i * (2*pi)/(float)N);
im[idx] = (float)-sin(4 * (float)i * (2*pi)/(float)N);
(3nd set of lines) expressed as following repeated 16 times consequently
re[idx] = (float) cos(16 * (float)i * (2*pi)/(float)N);
im[idx] = (float)-sin(16 * (float)i * (2*pi)/(float)N);
The result is expected to be as following:
//set 1 as above repeated just 1 time
// ....
//set 2 repeated 4 times
RE = 1.000000 IM = -0.000000 //1st ligne of set 1
RE = 0.995185 IM = -0.098017 //4th ligne of set 1
RE = 0.980785 IM = -0.195090 //8th ligne of set 1
RE = 0.956940 IM = -0.290285 //12th ligne of set 1 ...
RE = 0.923880 IM = -0.382683
RE = 0.881921 IM = -0.471397
RE = 0.831470 IM = -0.555570
RE = 0.773010 IM = -0.634393
RE = 0.707107 IM = -0.707107
RE = 0.634393 IM = -0.773010
RE = 0.555570 IM = -0.831470
RE = 0.471397 IM = -0.881921
RE = 0.382683 IM = -0.923880
RE = 0.290285 IM = -0.956940
RE = 0.195090 IM = -0.980785
RE = 0.098017 IM = -0.995185
// set 3 repeated 16 times
RE = 1.000000 IM = -0.000000 //1st ligne of set 1
RE = 0.923880 IM = -0.382683 //16th ligne of set 1
RE = 0.707107 IM = -0.707107 //38th ligne of set 1
RE = 0.382683 IM = -0.923880 //64th ligne of set 1
I've tried several times but i keep getting wrong results I don't know if it's precison issue or sometimng else.

You might maintain factor and set size in an additional (outer) loop:
// you will need more than you calculated previously!
float twiddle_real[TWIDDLE_LIMIT * 3];
float twiddle_imag[TWIDDLE_LIMIT * 3];
// pointer arithmetic...
float* real = twiddle_real;
float* imag = twiddle_imag;
double factor = 1.0;
for(int size = TWIDDLE_LIMIT; size > 1; size /= 4)
{
for(int j = 0; j < 64; ++j)
{
*real++ = (float) cos((j % size) * factor * 2.0 * PI / N);
*imag++ = (float) -sin((j % size) * factor * 2.0 * PI / N);
}
factor *= 4.0;
}
You do not need all those casts by the way - since factor is a double, (j % size) is converted to implicitly, as well as N afterwards.
Recommendation: As re and img belong together, I would represent them as such:
struct Complex
{
double re;
double im;
};
You could then have an array of these:
struct Complex twiddle[TW_size]; // no need for malloc, by the way...
You might have noticed: I changed to double, too. There is no reason to use float (with more limited precision) unless you have limited memory available (micro controllers)...
Alternative (why re-inventing the wheel?): use complex.h.

It doesn't work because your math is wrong. The first table covers only the first quadrant of the complex plane. When you multiply by 4 for the second segment of your desired output, you won't get 4 repeats of the first quadrant, you'll get all four quadrants.
Here is something closer to what you specified. And it fixes some problems with your use of C:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define N_ROOTS_OF_UNITY 64
#define PI 3.14159265358979323846264338327950
float *twiddle_real;
float *twiddle_imag;
int main()
{
size_t table_size = N_ROOTS_OF_UNITY * 3;
twiddle_real = malloc(table_size * sizeof(float));
twiddle_imag = malloc(table_size * sizeof(float));
size_t i, incr, repeat, k = 0;
for (incr = 1; incr <= 16; incr *= 4) {
for (repeat = 0; repeat < incr; ++repeat) {
for(i = 0; i < N_ROOTS_OF_UNITY; i += incr) {
twiddle_real[k] = (float) cos(i * (PI / 2) / N_ROOTS_OF_UNITY);
twiddle_imag[k] = (float) -sin(i * (PI / 2) / N_ROOTS_OF_UNITY);
++k;
}
}
}
for (int a = 0; a < table_size; a++)
printf("%d: RE = %f\tIM = %f\n", a, twiddle_real[a], twiddle_imag[a]);
return 0;
}

Related

Erroneous array reading inside a thread

I Have a multi-threaded C program where I have 4 threads doing some arithmetic computations using some global arrays. here is example of the code.
__m256 *array_1;
__m256 *array_2;
__m256 *array_3;
#define ALIGNMENT 32
#define SIMD_STEP 8
void Init_arrays()
{
int i;
posix_memalign((void**) &array_1, ALIGNMENT, 32*sizeof(__m256));
posix_memalign((void**) &array_2, ALIGNMENT, 4 *sizeof(__m256));
posix_memalign((void**) &array_3, ALIGNMENT, 2 *sizeof(__m256));
for(i=0;i < 256; i+= SIMD_STEP)
{
// Filling array for the 1st stage
}
for(i=0;i < 64; i+= SIMD_STEP)
{
// Filling array for the 2nd stage
}
for(i=0;i < 16; i+= SIMD_STEP)
{
// Filling array for the 3rd stage
}
}
void *routine(void *thread_info)
{
int n;
unsigned t_start,t_stop;
unsigned ind1, ind2, ind3;
float *arr_in , *arr_out;
struct thread_data *mydata;
mydata = (struct thread_data*) thread_info;
t_start = mydata->start;
t_stop = mydata->stop;
arr_in = mydata->input;
arr_out = mydata->output;
for (n = t_start; n < t_stop; n += 8)
{
ind1 = 256 + n;
ind2 = 512 + n;
vec_a = _mm256_load_ps((float *) (&arr_in[n ]) );
vec_b = _mm256_load_ps((float *) (&arr_in[ind1]) );
vec_c = _mm256_load_ps((float *) (&arr_in[ind2]) );
T_fac1 = array_1[n];
T_fac2 = array_2[n];
T_fac3 = array_3[n];
// print data 'printf()'
// further computations
_mm256_store_ps((float *) (&arr_out[n ]), (vec_a) );
_mm256_store_ps((float *) (&arr_out[ind1]), (vec_b) );
_mm256_store_ps((float *) (&arr_out[ind2]), (vec_c) );
}
pthread_exit(NULL);
}
void foo(float* in,float* out)
{
unsigned t,i=0;
for(t=0;t<256;t+=64)
{
thread_data_array[i].start = t;
thread_data_array[i].stop = t+QUARTER;
thread_data_array[i].input = in;
thread_data_array[i].output = out;
pthread_create(&threads[i],NULL,routine,(void*)&thread_data_array[i]);
i++;
}
for(i=0; i<NUM_THREADS; i++)
{
int rc = pthread_join(threads[i], NULL);
if (rc)
{
fprintf(stderr, "failed to join thread #%u - %s\n",i, strerror(rc));
}
}
}
int main()
{
float *data1;
float *data2;
posix_memalign((void**)&data1, 32, 1024 * sizeof(float));
posix_memalign((void**)&data2, 32, 1024 * sizeof(float));
Load_inputs(reals,imags);//load data into the two arrays
Init_arrays();
// print data 'printf()'
foo(data1,data2);
return EXIT_SUCCESS;
}
For some reason reading from the array_1 for example doesnt work as it should be inside the thread, and I did not know the reason behind it. Here is display of the array_1 as it should be
Display from the main Display from the thread
RE = 1.000000 IM = -0.000000 RE = 1.000000 IM = -0.000000
RE = 0.999981 IM = -0.006136 RE = 0.399624 IM = 0.671559
RE = 0.999925 IM = -0.012272 RE = 0.416430 IM = 0.634393
RE = 0.999831 IM = -0.018407 RE = 0.433094 IM = 0.595699
RE = 0.999699 IM = -0.024541 RE = 0.449612 IM = 0.555570
RE = 0.999529 IM = -0.030675 RE = 0.465977 IM = 0.514103
RE = 0.999322 IM = -0.036807 RE = 0.482184 IM = 0.471397
RE = 0.999078 IM = -0.042938 RE = 0.498228 IM = 0.427555
RE = 0.998795 IM = -0.049068 // the same
RE = 0.998476 IM = -0.055195 // the same
RE = 0.998118 IM = -0.061321 // the same
RE = 0.997723 IM = -0.067444 // the same
RE = 0.997290 IM = -0.073565 // the same
RE = 0.996820 IM = -0.079682 // the same
RE = 0.996313 IM = -0.085797 // the same
RE = 0.995767 IM = -0.091909 // the same
Could somebody know what is the reason behind this erroneous results?
Given
__m256 *array_1;
__m256 *array_2;
__m256 *array_3;
#define ALIGNMENT 32
#define SIMD_STEP 8
void Init_arrays()
{
int i;
posix_memalign((void**) &array_1, ALIGNMENT, 32*sizeof(__m256));
posix_memalign((void**) &array_2, ALIGNMENT, 4 *sizeof(__m256));
posix_memalign((void**) &array_3, ALIGNMENT, 2 *sizeof(__m256));
.
.
.
This loop references array elements that are way out of range:
for (n = t_start; n < t_stop; n += 8)
{
.
.
.
T_fac1 = array_1[n];
T_fac2 = array_2[n];
T_fac3 = array_3[n];
array_3 has all of two members: 2 *sizeof(__m256) yet the index is incremented by eight?

CUDA C - how to use Texture2D for double precision floating point

I want to use texture 2D memory for double precision. I want to read from texture to shared memory and convert int2 to double, and then transfer back to host memory But I am getting only first row as desired and all other row's value is 2.00000000.
#include<stdio.h>
#include<cuda.h>
#define Xdim 8
#define Ydim 8
texture<int2,2>me_texture;
static __inline__ __device__ double fetch_double(int2 p){
return __hiloint2double(p.y, p.x);
}
__global__ void kern(double *o, int pitch){
__shared__ double A[Xdim][Ydim];
unsigned int i = blockIdx.x*blockDim.x + threadIdx.x;
unsigned int j = blockIdx.y*blockDim.y + threadIdx.y;
int2 jj;
if(i<Xdim && j<Ydim){
jj = tex2D(me_texture, i, j);
A[threadIdx.x][threadIdx.y] = fetch_double(jj);
}
__syncthreads();
if(i<Xdim && j<Ydim){
o[j*Xdim + i] = A[threadIdx.x][threadIdx.y];
}
}
int main(int argc, char *argv[]){
double hbuf[Xdim][Ydim];
double hout[Xdim][Ydim];
double *dob;
double *dbuf;
size_t pitch_bytes;
cudaMallocPitch((void**)&dbuf, &pitch_bytes, sizeof(double)*Xdim, Ydim);
cudaMallocPitch((void**)&dob, &pitch_bytes, sizeof(double)*Xdim, Ydim);
hbuf[0][0] = 1.234567891234567;
hbuf[0][1] = 12.34567891234567;
hbuf[0][2] = 123.4567891234567;
hbuf[0][3] = 1234.567891234567;
hbuf[0][4] = 12345.67891234567;
hbuf[0][5] = 123456.7891234567;
hbuf[0][6] = 1234567.891234567;
hbuf[0][7] = 12345678.91234567;
hbuf[1][0] = 123456789.1234567;
hbuf[1][1] = 1234567891.234567;
hbuf[1][2] = 12345678912.34567;
hbuf[1][3] = 123456789123.4567;
hbuf[1][4] = 1234567891234.567;
hbuf[1][5] = 12345678912345.67;
hbuf[1][6] = 123456789123456.7;
hbuf[1][7] = 1234567891234567;
hbuf[2][0] = 123456789.7654321;
hbuf[2][1] = 1234567897.654321;
hbuf[2][2] = 12345678976.54321;
hbuf[2][3] = 123456789765.4321;
hbuf[2][4] = 1234567897654.321;
hbuf[2][5] = 12345678976543.21;
hbuf[2][6] = 123456789765432.1;
hbuf[2][7] = 1234567897654321;
hbuf[3][0] = 9.876543211234567;
hbuf[3][1] = 98.76543211234567;
hbuf[3][2] = 987.6543211234567;
hbuf[3][3] = 9876.543211234567;
hbuf[3][4] = 98765.43211234567;
hbuf[3][5] = 987654.3211234567;
hbuf[3][6] = 9876543.211234567;
hbuf[3][7] = 98765432.11234567;
hbuf[4][0] = 987654321.1234567;
hbuf[4][1] = 9876543211.234567;
hbuf[4][2] = 98765432112.34567;
hbuf[4][3] = 987654321123.4567;
hbuf[4][4] = 9876543211234.567;
hbuf[4][5] = 98765432112345.67;
hbuf[4][6] = 987654321123456.7;
hbuf[4][7] = 9876543211234567;
hbuf[5][0] = 987654321.7654321;
hbuf[5][1] = 9876543217.654321;
hbuf[5][2] = 98765432176.54321;
hbuf[5][3] = 987654321765.4321;
hbuf[5][4] = 9876543217654.321;
hbuf[5][5] = 98765432176543.21;
hbuf[5][6] = 987654321765432.1;
hbuf[5][7] = 9876543217654321;
hbuf[6][0] = 1234567891234567;
hbuf[6][1] = 123456789123456.7;
hbuf[6][2] = 12345678912345.67;
hbuf[6][3] = 1234567891234.567;
hbuf[6][4] = 123456789123.4567;
hbuf[6][5] = 12345678912.34567;
hbuf[6][6] = 1234567891.234567;
hbuf[6][7] = 123456789.1234567;
hbuf[7][0] = 12345678.91234567;
hbuf[7][1] = 1234567.891234567;
hbuf[7][2] = 123456.7891234567;
hbuf[7][3] = 12345.67891234567;
hbuf[7][4] = 1234.567891234567;
hbuf[7][5] = 123.4567891234567;
hbuf[7][6] = 12.34567891234567;
hbuf[7][7] = 1.234567891234567;
for (int i=0; i<Xdim; i++){
for(int j=0; j<Ydim; j++){
printf("%.16f\t", hbuf[i][j]);
}
printf("\n");
}
cudaMemcpy2D(dbuf, pitch_bytes, hbuf, Xdim*sizeof(double), Xdim*sizeof(double), Ydim, cudaMemcpyHostToDevice);
me_texture.addressMode[0] = cudaAddressModeClamp;
me_texture.addressMode[1] = cudaAddressModeClamp;
me_texture.filterMode = cudaFilterModeLinear;
me_texture.normalized = false;
cudaBindTexture2D(0, me_texture, dbuf, cudaCreateChannelDesc(32,32,0,0, cudaChannelFormatKindSigned), Xdim, Ydim, pitch_bytes );
int pitch = pitch_bytes/sizeof(double);
kern<<<1, 64>>>(dob, pitch);
cudaMemcpy2D(hout,Xdim*sizeof(double), dob, pitch_bytes, Xdim*sizeof(double),Ydim, cudaMemcpyDeviceToHost);
printf("\nI am Fine\n");
for(int i = 0 ; i < Xdim ; i++){
for(int j=0; j<Ydim; j++){
printf("%.16f\t", hout[i][j]);
}
printf("\n");
}
cudaUnbindTexture(me_texture);
cudaFree(dbuf);
cudaFree(dob);
return 0;
}
Above code work fine if you change the following things.
Replace
kern<<<1, 64>>>(..., ..)
to
dim3 blockPerGrid(1, 1)
dim3 threadPerBlock(8, 8)
kern<<<blockPerGrid, threadPerBlock>>>(....)
here in place of Xdim change it to pitch
o[j*pitch + i] = A[threadIdx.x][threadIdx.y];
And change cudaFilterModeLinear to cudaFilterModePoint .
For the compilation you need to specify the computing capability, suppose your compute capability ie 3.0 then it would be
nvcc -arch=sm_30 file.cu
If your code contained error checking, you would realise that your kernel launch is failing with an invalid filter mode. It isn't legal in CUDA to use a cudaFilterModeLinear with non-float types, so nothing is actually running. If you change the filter mode to cudaFilterModePoint, you might find things start working.

3D / 4D Matrix manipulation

I often struggle with slow Matlab processing due to high numbers of for loops.
Maybe you can help me with this example, which would help me in other cases as well: Is it possible to completely transfer it to matrices?
R = [1 2 3; 1 2 3; 1 2 3];
u1 = 200; u2 = 300; v1 = 100; v2 = 222; w1 = 123; w2 = 312;
px = 20; py = 30; pz = 25;
a = 20; b = 30; c = 25;
Ellipse = zeros(500,600,500)
for i=u1:u2
for j=v1:v2
for k=w1:w2
x=[i-px;j-py;k-pz];
x=R*x;
if (x(1)/a)^2+(x(2)/b)^2+(x(3)/c)^2<1
Ellipse(i,j,k)=1;
end
end
end
end
Here's one approach that runs about 2 orders of magnitude faster
R = [1 2 3; 1 2 3; 1 2 3];
u1 = 200; u2 = 300; v1 = 100; v2 = 222; w1 = 123; w2 = 312;
px = 20; py = 30; pz = 25;
a = 20; b = 30; c = 25;
Ellipse = zeros(500,600,500);
% Create mesh of points to process
vx = (u1:u2) - px;
vy = (v1:v2) - py;
vz = (w1:w2) - pz;
[X,Y,Z] = meshgrid(vx, vy, vz);
% Compute R*x
V = [X(:)'; Y(:)'; Z(:)'];
V = R * V;
% Divide by ellipse axes
M = diag([1/a, 1/b, 1/c]);
V = M * V;
% Determine if norm criteria is met
index = norm(V') < 1;
Ellipse(X(index), Y(index), Z(index)) = 1;
Agree with #Dan, a smaller working example would make it easier to test.
If you are doing more than simple mathematical operations matrices can be tricky.
Here you can (should) reduce the size of Ellipse because you are not using most of its entries.
All you need is (101,123,190) and things will be much faster, especially the way you are accessing the matrix entries, remember MATLAB will eventually store the matrix as just an array.
#dpmcmlxxvi Thank you very much for the answer. At first, sorry for the large example. I used your answer with some modification as norm(XY) did not work for me.(smaller example and valueas adapted to run properly)
R = [1 2 3; 1 2 3; 1 2 3];
u1 = 50; u2 = 90; v1 = 20; v2 = 50; w1 = 30; w2 = 60;
px = 60; py = 25; pz = 50;
a = 10; b = 20; c = 15;
Ellipse = zeros(100,200,100);
% Create mesh of points to process
vx = (u1:u2) - px;
vy = (v1:v2) - py;
vz = (w1:w2) - pz;
[X,Y,Z] = meshgrid(vx, vy, vz);
% Compute R*x
V = [X(:)'; Y(:)'; Z(:)'];
V = R * V;
% Divide by ellipse axes
M = diag([1/a, 1/b, 1/c]);
V = M * V;
% Apply criteria
Vsq = V.*V;
crit = Vsq(1,:)+Vsq(2,:)+Vsq(3,:);
% Look for indices in the meshgrid fullfilling criteria
xe = X(find(crit<1));
ye = Y(find(crit<1));
ze = Z(find(crit<1));
xi = ceil(abs(xe+px));
yi = ceil(abs(ye+py));
zi = ceil(abs(ze+pz));
% Set values at correpsonding indices to 1
linind = sub2ind(size(Ellipse),xi,yi,zi);
Ellipse(linind) = 1;
It works fine and all for loops have been removed.

PI control algorithm manually implemented in matlab

I'm trying to implement a simple script performing a PI control for a cruise control application, but I'm founding some problems with the integral part. Here is my code:
function [] = PI_cruisecontrol()
clc; close all;
t0 = 0; tfinal = 50; dt = 0.001; % time parameters
r = 10; % reference of 10 m/s
m = 1000; % mass
b = 50; % friction coeff. (depends on v)
yp = zeros(tfinal/dt,1); t = yp; % initialize speed and time array
Ki = 40; % integrarl constant
Kp = 800; % proportional constant
int = 0; % itinialize int error
% CONTROL LOOP (Forward-Euler integrator is used to solve the ODE)
for i=t0+2:tfinal/dt
err = r-yp(i-1); % update error
int = int+err; % integral term
u = (Kp*err)+(Ki*int*dt); % action of control
yp(i) = yp(i-1)+((-b*yp(i)/m) + (u/m))*dt; % solve ode for speed
t(i) = t(i)+dt*i; % log the time
end
% Results
figure(1)
plot(t,yp)
title ('Step Response')
xlabel('Time (seconds)')
ylabel('Amplitud')
axis([0 20 0 12])
hold on
reference = ones(tfinal/dt,1)*10;
plot(t,reference,':')
end
And this is how it should be, using predefinided matlab functions:
function [] = PI_cruisecontrol2()
m = 1000;
b = 50;
r = 10;
s = tf('s');
P_cruise = 1/(m*s + b);
Kp = 800;
Ki = 40;
C = pid(Kp,Ki);
T = feedback(C*P_cruise,1);
t = 0:0.1:20;
step(r*T,t)
axis([0 20 0 12])
end
What am I doing wrong in my code?
Thanks!
I managed to fix the problem, working with float variables instead of arrays. Moreover, I added the derivative term (although for this first order problem was not necessary)
Here I left the code:
function [] = aFortran_PI()
clc; close all;
r = 10; % reference of 10 m/s
m = 1000; % mass
b = 50; % friction coeff. (depends on v)
yp = 0; % init response
Kp = 800; % proportional constant
Ki = 40; % proportional constant
Kd = 0; % derivative term is not necessary in this problem
previous_error = 0;
integral = 0;
dt = 0.001;
% CONTROL LOOP
for i=1:20000
error = r-yp; % update error
integral = integral + error*dt; % integral term
derivative = (error-previous_error)/dt; % derivative term
u = Kp*error+Ki*integral+Kd*derivative; % action of control
yp = yp+(-b*yp/m + u/m)*dt % solve ode for velocity
end
end

How to visualize microphone sound/pressure level in Silverlight 4?

I was following this tutorial on how to make a Silverlight audio recorder. I thought it would be great to add a volume bar indicator to provide user with a feedback on what's happening. However, I can't seem to get this to work properly.
OnSamples method of AudioSink class provides raw PCM data as one of the arguments. Also, I set the AudioFrameSize property of AudioCaptureDevice to 40 (1000/40 == 25fps), so OnSamples is triggered every 40ms.
My question is how to extract the sound volume information from PCM data and display it as percentage in a progress bar [0-100]?
This is what I have so far:
double average = 0;
for (int a = 0; a < sampleData.Length; ++a)
{
average += Math.Abs(sampleData[a]);
}
average /= sampleData.Length;
double volume = 20 * Math.Log10(average);
Value of the progress bar is then set to volume:
progressBar.Value = volume;
My code doesn't work, apparently, since the volume value is almost always at the same level.
Any help is appreciated!
try this...this is for (8000,8,1) if you are using 2 channels replace "index+=1" with "index+=2"
for (int index = 0; index < sampleData.Length; index += 1)
{
short sample = (short)((sampleData[index + 1] << 8) | sampleData[index + 0]);
//short sample = (short)(sampleData[index + 0]);
float sample32 = sample / 32768f;
float maxValue = 0;
float minValue = 0;
maxValue = Math.Max(maxValue, sample32);
minValue = Math.Min(minValue, sample32);
float lastPeak = Math.Max(maxValue, Math.Abs(minValue));
this.MicLevel = (100 - (lastPeak * 100)) * 10;
//System.Diagnostics.Debug.WriteLine("Mic Level: " + this.MicLevel.ToString());
}

Resources