wav_file *open_wav(char *filename) { wav_file *state = (wav_file*)malloc(sizeof(wav_file)); state->file = fopen(filename,"rb"); if(state->file==NULL) { free(state); return(NULL); } state->filename = (char*)malloc(strlen(filename)+1); strcpy(state->filename,filename); state->header = (wav_header*)malloc(sizeof(wav_header)); state->sample_buffer=NULL; state->sample_buffer_length=0; memset(state->header,0,sizeof(wav_header)); int r = fread((void*)state->header,sizeof(wav_header),1,state->file); if(!r) { close_wav(state); return(NULL); } /*header sanity check*/ if(memcmp(state->header->riff_magic,&RIFF_MAGIC,4) || memcmp(state->header->wave_magic,&WAVE_MAGIC,4) || memcmp(state->header->wave_chunk_magic,&WAVE_CHUNK_MAGIC,4) || memcmp(state->header->wave_chunk_data_magic,&WAVE_CHUNK_DATA_MAGIC,4) || state->header->format_tag != PCM_FORMAT_TAG) { printf("sanity check failed\n"); close_wav(state); return(NULL); } state->offset = WAVE_HEADER_LENGTH; //set offset to beginning of data printf("samplerate: %dhz\n",get_samplerate(state)); printf("bitrate: %d\n",state->header->bitrate); printf("channels: %d\n",state->header->channels); printf("bits per sample: %d\n",state->header->bits_per_sample); printf("block align: %d\n",state->header->block_align); printf("format_tag: %d\n",state->header->format_tag); state->samples_num = state->header->wave_chunk_data_length/state->header->block_align; //use a 1000 samples buffer unsigned long sample_buffer_num = 1000; if(state->samples_num<sample_buffer_num) sample_buffer_num = state->samples_num; state->sample_buffer_length = state->header->block_align*sample_buffer_num; state->sample_buffer = (void*)malloc(state->sample_buffer_length); printf("created a %d bytes samples buffer\n",state->sample_buffer_length); printf("number of samples: %d\n",state->samples_num); if(!fill_sample_buffer(state)) { close_wav(state); return(NULL); } return(state); }
int effect_reset(struct razer_fx_render_node *render) { //reopen input file char *filename = daemon_get_parameter_string(daemon_effect_get_parameter_by_index(render->effect,0)); if(effect_input_file) { close_wav(effect_input_file); effect_input_file = NULL; } effect_input_file =open_wav(filename); #ifdef USE_DEBUGGING printf("(fft) opened input wav file:%s,%x\n",filename); #endif if(effect_input_file) return(1); else return(0); }
int effect_update(struct razer_fx_render_node *render) { float magnitude = daemon_get_parameter_float(daemon_effect_get_parameter_by_index(render->effect,1)); int x,y; struct razer_rgb col; #ifdef USE_DEBUGGING printf(" (Fft.%d ## %%:%f)",render->id); #endif unsigned long samples_left=0; while((samples_left=wav_samples_left(effect_input_file))) { unsigned int sample = read_wav_stereo_sample(effect_input_file); short high = sample >> 16; short low = sample & 0xFFFF; //add sample to fft buffer effect_fft_in[effect_fft_samples_used][0] = (double)high * effect_fft_hamming_buffer[effect_fft_samples_used];///(double)32768;//* windowHanning(step++, N); effect_fft_in[effect_fft_samples_used++][1] = 0.0f; //enough samples gathered? if(effect_fft_samples_used==effect_fft_samples) { printf("Computing fft, still %d samples left\n",samples_left); //compute fft effect_fft_plan = fftw_plan_dft_1d(effect_fft_samples, effect_fft_in, effect_fft_out, FFTW_FORWARD, FFTW_ESTIMATE); fftw_execute(effect_fft_plan); fftw_destroy_plan(effect_fft_plan); effect_fft_samples_used = 0; double tmp_magnitude = sqrt(effect_fft_out[0][0]*effect_fft_out[0][0] + effect_fft_out[0][1]*effect_fft_out[0][1]); tmp_magnitude = 10./log(10.) * log(tmp_magnitude + 1e-6); printf("new fft mag db:%f\n",tmp_magnitude); double sum = 0.0f; for(int i=0;i<effect_fft_samples/2;i++) { double tmp_bin_magnitude = sqrt(effect_fft_out[i][0]*effect_fft_out[i][0] + effect_fft_out[i][1]*effect_fft_out[i][1]); tmp_bin_magnitude = 10./log(10.) * log(tmp_bin_magnitude + 1e-6); sum += tmp_bin_magnitude; } printf("sum:%f\n",sum/(effect_fft_samples/2)); magnitude = (float)tmp_magnitude - 50.0f; break; } } if(!samples_left) { #ifdef USE_DEBUGGING printf("no samples left to analyze, closing input file\n"); #endif close_wav(effect_input_file); effect_input_file = NULL; return(0); } //set color to avg magnitude ,transformed to 0.0-1.0 space //calculate hue from magnitude rgb_from_hue(magnitude/96,0.3f,0.0f,&col); for(x=0;x<22;x++) for(y=0;y<6;y++) { rgb_mix_into(&render->output_frame->rows[y].column[x],&render->input_frame->rows[y].column[x],&col,render->opacity);//*render->opacity //&render->second_input_frame->rows[y].column[x] render->output_frame->update_mask |= 1<<y; } daemon_set_parameter_float(daemon_effect_get_parameter_by_index(render->effect,1),magnitude); return(1); }
int main(int argc, char *argv[]) { int fd, fd_dec; int res, datasize,i; int nb_frames = 0; #ifdef DUMP_RAW_FRAMES char filename[15]; int fd_out; #endif int32_t outbuf[2048]; uint16_t fs,sps,h; uint32_t packet_count; COOKContext q; RMContext rmctx; RMPacket pkt; memset(&q,0,sizeof(COOKContext)); memset(&rmctx,0,sizeof(RMContext)); memset(&pkt,0,sizeof(RMPacket)); if (argc != 2) { DEBUGF("Incorrect number of arguments\n"); return -1; } fd = open(argv[1],O_RDONLY); if (fd < 0) { DEBUGF("Error opening file %s\n", argv[1]); return -1; } /* copy the input rm file to a memory buffer */ uint8_t * filebuf = (uint8_t *)calloc((int)filesize(fd),sizeof(uint8_t)); res = read(fd,filebuf,filesize(fd)); fd_dec = open_wav("output.wav"); if (fd_dec < 0) { DEBUGF("Error creating output file\n"); return -1; } res = real_parse_header(fd, &rmctx); packet_count = rmctx.nb_packets; rmctx.audio_framesize = rmctx.block_align; rmctx.block_align = rmctx.sub_packet_size; fs = rmctx.audio_framesize; sps= rmctx.block_align; h = rmctx.sub_packet_h; cook_decode_init(&rmctx,&q); /* change the buffer pointer to point at the first audio frame */ advance_buffer(&filebuf, rmctx.data_offset+ DATA_HEADER_SIZE); while(packet_count) { rm_get_packet(&filebuf, &rmctx, &pkt); //DEBUGF("total frames = %d packet count = %d output counter = %d \n",rmctx.audio_pkt_cnt*(fs/sps), packet_count,rmctx.audio_pkt_cnt); for(i = 0; i < rmctx.audio_pkt_cnt*(fs/sps) ; i++) { /* output raw audio frames that are sent to the decoder into separate files */ #ifdef DUMP_RAW_FRAMES snprintf(filename,sizeof(filename),"dump%d.raw",++x); fd_out = open(filename,O_WRONLY|O_CREAT|O_APPEND, 0666); write(fd_out,pkt.frames[i],sps); close(fd_out); #endif nb_frames = cook_decode_frame(&rmctx,&q, outbuf, &datasize, pkt.frames[i] , rmctx.block_align); rmctx.frame_number++; res = write(fd_dec,outbuf,datasize); } packet_count -= rmctx.audio_pkt_cnt; rmctx.audio_pkt_cnt = 0; } close_wav(fd_dec, &rmctx, &q); close(fd); return 0; }