/* Analog VU meter plugin for xmms * * Copyright (C) 2002 Pekka Harjamäki * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include #include #include #include #include "vumeter.h" /* * Define external variables */ extern gint worker_running; extern gint16 shared_pcm_data[2][512]; extern GdkPixmap *doublebuf; extern GtkWidget *area; extern struct vumeter_cfg_info vumeter_cfg; extern struct vumeter_skin_info vumeter_skin; extern pthread_mutex_t pcm_data_lock; extern float left_needle_power[max_avarage_samples], right_needle_power[max_avarage_samples]; /**************************************** * Worker thread ****************************************/ void *vumeter_worker(void *arg) { long delay_value; int c, b=0; float max=32767.50, db_min=(float)vumeter_skin.db_min_range, channel_data[2]={0.0,0.0}; struct timezone tz; struct timeval tv_cur,tv_past; // Set initial value gettimeofday(&tv_past,&tz); // Start thread loop while(worker_running>0) { do { // Test to see, if thread should shutdown if(worker_running==0) pthread_exit(NULL); // Do we have new data packet waiting? if(worker_running==2) { // Reset values channel_data[0]=0.0; channel_data[1]=0.0; // Store value to make sure it does not change from now on.. b=vumeter_cfg.av_samples; // Make sure, that data does not change if(pthread_mutex_trylock(&pcm_data_lock)) { printf("Data race condition\n"); pthread_mutex_lock(&pcm_data_lock); } // Process sound data for(c=0; c<512; c+=2) { channel_data[0]+=(float)(shared_pcm_data[0][c]*shared_pcm_data[0][c]); channel_data[1]+=(float)(shared_pcm_data[1][c]*shared_pcm_data[1][c]); } // Reset datapacket value if(worker_running==2) worker_running=1; // Release datalock pthread_mutex_unlock(&pcm_data_lock); // Calculate dBFS values for both channels using // avarage of 256 samples channel_data[0]=20*log10( sqrt(channel_data[0]/256.0) / max ); channel_data[1]=20*log10( sqrt(channel_data[1]/256.0) / max ); for(c=b; c>=1; c--) { left_needle_power[c]=left_needle_power[c-1]; right_needle_power[c]=right_needle_power[c-1]; } // Make sure, that value is never below db_min (default -91) dBFS if(channel_data[0]0) pthread_exit(NULL); }