static void rvbap_bang(t_rvbap *x) // top level, vbap gains are calculated and outputted { t_atom at[MAX_LS_AMOUNT]; t_float g[3]; long ls[3]; long i; t_float *final_gs, overdist, oversqrtdist; final_gs = (t_float *) getbytes(x->x_ls_amount * sizeof(t_float)); if(x->x_lsset_available ==1){ vbap(g, ls, x); for(i=0;i<x->x_ls_amount;i++) final_gs[i]=0.0; for(i=0;i<x->x_dimension;i++){ final_gs[ls[i]-1]=g[i]; } if(x->x_spread != 0){ spread_it(x,final_gs); } overdist = 1 / x->x_dist; oversqrtdist = 1 / sqrt(x->x_dist); // build output for every loudspeaker for(i=0;i<x->x_ls_amount;i++) { // first, we output the gains for the direct (unreverberated) signals // these just decrease as the distance increases #ifdef MAXMSP SETLONG(&at[0], i); SETFLOAT(&at[1], (final_gs[i] / x->x_dist)); outlet_list(x->x_outlet0, NULL, 2, at); #endif #ifdef PD SETFLOAT(&at[0], i); SETFLOAT(&at[1], (final_gs[i] / x->x_dist)); outlet_list(x->x_outlet0, gensym("list"), 2, at); #endif // second, we output the gains for the reverberated signals // these are made up of a global (all speakers) and a local part #ifdef MAXMSP SETLONG(&at[0], i+x->x_ls_amount); // direct signals come first in matrix~ SETFLOAT(&at[1], (((oversqrtdist / x->x_dist) * x->x_reverb_gs[i]) + (oversqrtdist * (1 - overdist) * final_gs[i]))); outlet_list(x->x_outlet0, NULL, 2, at); #endif #ifdef PD SETFLOAT(&at[0], (i+x->x_ls_amount)); // direct signals come first in matrix~ SETFLOAT(&at[1], (((oversqrtdist / x->x_dist) * x->x_reverb_gs[i]) + (oversqrtdist * (1 - overdist) * final_gs[i]))); outlet_list(x->x_outlet0, gensym("list"), 2, at); #endif } #ifdef MAXMSP outlet_int(x->x_outlet1, x->x_azi); outlet_int(x->x_outlet2, x->x_ele); outlet_int(x->x_outlet3, x->x_spread); outlet_float(x->x_outlet4, (double)x->x_dist); #endif #ifdef PD outlet_float(x->x_outlet1, x->x_azi); outlet_float(x->x_outlet2, x->x_ele); outlet_float(x->x_outlet3, x->x_spread); outlet_float(x->x_outlet4, x->x_dist); #endif } else post("rvbap: Configure loudspeakers first!"); freebytes(final_gs, x->x_ls_amount * sizeof(t_float)); // bug fix added 9/00 }
static void rvbap_matrix(t_rvbap *x, t_symbol *s, int ac, t_atom *av) // read in loudspeaker matrices // and calculate the gains for the equally distributed // reverb signal part (i.e. global reverb) { long counter=0; long datapointer=0; long setpointer=0; long i; long deb=0; long azi = x->x_azi, ele = x->x_ele; // store original values t_float g[3]; long ls[3]; if(ac>0) #ifdef MAXMSP if(av[datapointer].a_type == A_LONG){ x->x_dimension = av[datapointer++].a_w.w_long; x->x_lsset_available=1; } else #endif if(av[datapointer].a_type == A_FLOAT){ x->x_dimension = (long) av[datapointer++].a_w.w_float; x->x_lsset_available=1; } else { post("Error in loudspeaker data!"); x->x_lsset_available=0; return; } //post("%d",deb++); if(ac>1) #ifdef MAXMSP if(av[datapointer].a_type == A_LONG) x->x_ls_amount = av[datapointer++].a_w.w_long; else #endif if(av[datapointer].a_type == A_FLOAT) x->x_ls_amount = (long) av[datapointer++].a_w.w_float; else { post("rvbap: Error in loudspeaker data!"); x->x_lsset_available=0; return; } else x->x_lsset_available=0; if(x->x_dimension == 3) counter = (ac - 2) / ((x->x_dimension * x->x_dimension*2) + x->x_dimension); if(x->x_dimension == 2) counter = (ac - 2) / ((x->x_dimension * x->x_dimension) + x->x_dimension); x->x_lsset_amount=counter; if(counter<=0) { post("rvbap: Error in loudspeaker data!"); x->x_lsset_available=0; return; } while(counter-- > 0){ for(i=0; i < x->x_dimension; i++){ #ifdef MAXMSP if(av[datapointer].a_type == A_LONG) #endif #ifdef PD if(av[datapointer].a_type == A_FLOAT) #endif { x->x_lsset[setpointer][i]=(long)av[datapointer++].a_w.w_float; } else{ post("rvbap: Error in loudspeaker data!"); x->x_lsset_available=0; return; } } for(i=0; i < x->x_dimension*x->x_dimension; i++){ if(av[datapointer].a_type == A_FLOAT){ x->x_set_inv_matx[setpointer][i]=av[datapointer++].a_w.w_float; } else { post("rvbap: Error in loudspeaker data!"); x->x_lsset_available=0; return; } } if(x->x_dimension == 3){ for(i=0; i < x->x_dimension*x->x_dimension; i++){ if(av[datapointer].a_type == A_FLOAT){ x->x_set_matx[setpointer][i]=av[datapointer++].a_w.w_float; } else { post("rvbap: Error in loudspeaker data!"); x->x_lsset_available=0; return; } } } setpointer++; } // now configure static reverb correction values... x->x_azi = x->x_ele = 0; vbap(g,ls, x); for(i=0;i<x->x_ls_amount;i++){ x->x_reverb_gs[i]=0.0; } for(i=0;i<x->x_dimension;i++){ x->x_reverb_gs[ls[i]-1]=g[i]; // post("reverb gs #%d = %f", i, x->x_reverb_gs[i]); } equal_reverb(x,x->x_reverb_gs); /* for(i=0; i<x->x_ls_amount; i++) // do this for every speaker { post("reverb gs #%d = %f", i, x->x_reverb_gs[i]); } */ post("rvbap: Loudspeaker setup configured!"); x->x_azi = azi; // restore original panning directions x->x_ele = ele; }
main() { LS_DATA ls_data; FILE *fp; double gains[MAX_CHANNELS]; int azimuth=-10; int elevation=14; double *gainptr, gain; short *inptr,*outptr; short out[BUFFER_LENGTH][MAX_CHANNELS]; ALconfig c; AFfilehandle fh; ALport p; short *in; long frames; int i,j,k; int numchannels = 8; /* change this according your output device*/ int ls_set_dim = 3; int ls_num = 8; int ls_dirs[MAX_FIELD_AM]={-30,0, 30,0, -45,45, 45,45, -90,0, 90,0, 180,0, 180,45}; /* change these according to your loudspeaker positioning*/ /* defining loudspeaker data */ define_loudspeakers(&ls_data, ls_set_dim, ls_num, ls_dirs); /* ls_data is a struct containing matrices etc ls_set_dim is 2 if loudspeakers are on a (horizontal) plane ls_set_dim is 3 if also elevated or descended loudpeakers exist ls_num is the number of loudspeakers ls_dirs is an array containing the angular directions of loudsp*/ /* gain factors for virtual source in direction (int azimuth, int elevation) */ vbap(gains, &ls_data, azimuth, elevation); /* panning monophonic stream float *in to multiple outputs float *out[] with gain factors float *gains */ /* input audio*/ if((fh=afOpenFile("myaiff.aiff","r",0))==NULL){ fprintf(stderr, "Could not open file myaiff.aiff\n"); exit(-1); } frames=AFgetframecnt(fh,AF_DEFAULT_TRACK); if(afGetChannels(fh, AF_DEFAULT_TRACK) != 1){ fprintf(stderr, "Supports only mono aiff-files\n"); exit(-1); } in= malloc(frames*sizeof(short)*2); afReadFrames(fh,AF_DEFAULT_TRACK,in,frames); /*opening the audio port*/ c = alNewConfig(); if (!c) { printf("Couldn't create ALconfig:%s\n", alGetErrorString(oserror())); exit(-1); } alSetChannels(c,numchannels); ALsetqueuesize(c,BUFFER_LENGTH); p = alOpenPort("alVBAP example","w",c); if (!p) { printf("port open failed:%s\n", alGetErrorString(oserror())); exit(-1); } fprintf(stderr,"\nPanning audio"); for(j=0;j<(frames/BUFFER_LENGTH);j++){ inptr = &(in[j*BUFFER_LENGTH]); /* audio to be panned */ outptr= out[0]; for (i=0; i<BUFFER_LENGTH; i++){ /* panning */ gainptr=gains; for (k=0; k<numchannels; k++){ *outptr++ = (short) ((double) *inptr * *gainptr++); } inptr++; } alWriteFrames(p, out, BUFFER_LENGTH); /* write frames */ fprintf(stderr,"."); } /*write rest samples out*/ inptr = &(in[j*BUFFER_LENGTH]); /* partial buffer */ outptr= out[0]; for (i=0; i<(frames-BUFFER_LENGTH*j); i++){ /* panning */ gainptr=gains; for (k=0; k<numchannels; k++){ *outptr++ = (short) ((double) *inptr * *gainptr++); } inptr++; } for (;i<BUFFER_LENGTH; i++){ /* zeros */ for (k=0; k<numchannels; k++){ *outptr++ = 0; } } alWriteFrames(p, out, BUFFER_LENGTH); /* write frames */ fprintf(stderr,"."); printf("\n\nDone!\n\n"); }