Commit d091181a authored by Monty Montgomery's avatar Monty Montgomery

Changes leading up to hooking in declipping filter; it's not there
yet, but I don;t want to lose work.

Monty


git-svn-id: https://svn.xiph.org/trunk/postfish@5714 0101bb08-14d6-0310-b084-bc0e0c8e3800
parent bf77bf36
......@@ -6,9 +6,9 @@ CC=gcc
LD=gcc
SRC = main.c mainpanel.c multibar.c readout.c input.c output.c clippanel.c declip.c \
reconstruct.c smallft.c
reconstruct.c smallft.c windowbutton.c subpanel.c feedback.c
OBJ = main.o mainpanel.o multibar.o readout.o input.o output.o clippanel.o declip.o \
reconstruct.o smallft.o
reconstruct.o smallft.o windowbutton.o subpanel.o feedback.o
GCF = `pkg-config --cflags gtk+-2.0` -DG_DISABLE_DEPRECATED -DGDK_DISABLE_DEPRECATED -DGTK_DISABLE_DEPRECATED -DGDK_PIXBUF_DISABLE_DEPRECATED
all:
......
This diff is collapsed.
#include "postfish.h"
typedef struct postfish_clippanel {
GtkWidget *toplevel;
postfish_mainpanel *mainpanel;
} postfish_clippanel;
extern void clippanel_create(postfish_clippanel *panel,
postfish_mainpanel *mp);
extern void clippanel_show(postfish_clippanel *p);
extern void clippanel_hide(postfish_clippanel *p);
extern void clippanel_create(postfish_mainpanel *mp,
GtkWidget *windowbutton,
GtkWidget *activebutton);
extern void clippanel_feedback(void);
extern void clippanel_reset(void);
......@@ -26,6 +26,7 @@
#include <sys/types.h>
#include "smallft.h"
#include "reconstruct.h"
#include "feedback.h"
#include <stdio.h>
extern int input_rate;
......@@ -76,25 +77,61 @@ static int cache_samples;
static int fillstate=0; /* 0: uninitialized
1: normal
2: eof processed */
static time_linkage out;
/* accessed across threads */
static sig_atomic_t declip_active=0;
static sig_atomic_t declip_converge=2; /* 0=over, 1=full, 2=half, 3=partial, 4=approx */
static sig_atomic_t *chtrigger=0;
static sig_atomic_t *chactive=0;
sig_atomic_t declip_active=0;
sig_atomic_t declip_converge=2; /* 0=over, 1=full, 2=half, 3=partial, 4=approx */
static double *chtrigger=0;
static sig_atomic_t pending_blocksize=0;
static double convergence=0.;
static double iterations=0.;
/* feedback! */
typedef struct declip_feedback{
feedback_generic parent_class;
int *clipcount;
int total;
} declip_feedback;
static feedback_generic_pool feedpool;
static feedback_generic *new_declip_feedback(void){
declip_feedback *ret=malloc(sizeof(*ret));
ret->clipcount=malloc((input_ch)*sizeof(*ret->clipcount));
return (feedback_generic *)ret;
}
static void push_declip_feedback(int *clip,int total){
int i,n=input_ch;
declip_feedback *f=(declip_feedback *)
feedback_new(&feedpool,new_declip_feedback);
memcpy(f->clipcount,clip,n*sizeof(*clip));
f->total=total;
feedback_push(&feedpool,(feedback_generic *)f);
}
int pull_declip_feedback(int *clip,int *total){
declip_feedback *f=(declip_feedback *)feedback_pull(&feedpool);
int i,j;
if(!f)return 0;
if(clip)memcpy(clip,f->clipcount,sizeof(*clip)*input_ch);
if(total)*total=f->total;
feedback_old(&feedpool,(feedback_generic *)f);
return 1;
}
/* called only by initial setup */
int declip_load(void){
int i;
chtrigger=malloc(input_ch*sizeof(*chtrigger));
chactive=malloc(input_ch*sizeof(*chactive));
for(i=0;i<input_ch;i++){
chtrigger[i]=0x80000000UL;
chactive[i]=1;
}
for(i=0;i<input_ch;i++)
chtrigger[i]=1.;
out.size=input_size;
out.channels=input_ch;
......@@ -121,22 +158,31 @@ int declip_setblock(int n){
return 0;
}
int declip_setactive(int activep,int ch){
int declip_settrigger(double trigger,int ch){
if(ch<0 || ch>=input_ch)return -1;
chactive[ch]=activep;
pthread_mutex_lock(&master_mutex);
chtrigger[ch]=trigger;
pthread_mutex_unlock(&master_mutex);
return 0;
}
int declip_settrigger(double trigger,int ch){
if(ch<0 || ch>=input_ch)return -1;
chtrigger[ch]=rint(trigger*(1.*0x80000000UL));
return 0;
int declip_setiterations(double it){
pthread_mutex_lock(&master_mutex);
iterations=it;
pthread_mutex_unlock(&master_mutex);
}
int declip_setconvergence(double c){
pthread_mutex_lock(&master_mutex);
convergence=c;
pthread_mutex_unlock(&master_mutex);
}
/* called only in playback thread */
int declip_reset(void){
/* reset cached pipe state */
fillstate=0;
while(pull_declip_feedback(NULL,NULL));
return 0;
}
......@@ -199,12 +245,12 @@ static void sliding_bark_average(double *f,double *w, int n,double width){
}
static void declip(double *data,double *lap,double *out,
int blocksize,unsigned long trigger){
int blocksize,double trigger,
double epsilon, double iteration,
int *runningtotal, int *runningcount){
double freq[blocksize];
int flag[blocksize];
double triggerlevel=trigger*(1./0x80000000UL);
double epsilon=1e-12;
int iterbound=blocksize,i,j,count=0;
int iterbound,i,j,count=0;
for(i=0;i<blocksize/8;i++)flag[i]=0;
for(;i<blocksize*7/8;i++){
......@@ -212,52 +258,67 @@ static void declip(double *data,double *lap,double *out,
if(data[i]>=trigger || data[i]<=-trigger){
flag[i]=1;
count++;
*runningcount++;
}
}
for(;i<blocksize;i++)flag[i]=0;
for(i=0;i<blocksize;i++)data[i]*=window[i];
memcpy(freq,data,sizeof(freq));
drft_forward(&fft,freq);
sliding_bark_average(freq,freq,blocksize,width);
switch(declip_converge){
case 0:
epsilon=1e-12;
iterbound=blocksize*2;
break;
case 1:
epsilon=1e-8;
iterbound=count;
break;
case 2:
epsilon=1e-6;
iterbound=count/2;
break;
case 3:
epsilon=1e-5;
iterbound=count/4;
break;
case 4:
epsilon=1e-3;
iterbound=count/8;
break;
}
if(iterbound<20)iterbound=20;
*runningtotal+=blocksize*3/4;
if(declip_active){
for(;i<blocksize;i++)flag[i]=0;
for(i=0;i<blocksize;i++)data[i]*=window[i];
memcpy(freq,data,sizeof(freq));
drft_forward(&fft,freq);
sliding_bark_average(freq,freq,blocksize,width);
if(iteration<1.){
iterbound=count*iteration;
}else{
iterbound=count+blocksize*(iteration-1.);
}
if(iterbound<20)iterbound=20;
reconstruct(&fft,data,freq,flag,epsilon*count,iterbound,blocksize);
reconstruct(&fft,data,freq,flag,epsilon*count,iterbound,blocksize);
if(out)
for(i=0;i<blocksize/2;i++)
out[i]=lap[i]+data[i]*window[i];
for(i=blocksize/2,j=0;i<blocksize;i++)
lap[j]=data[i]*window[i];
if(out)
for(i=0;i<blocksize/2;i++)
out[i]=lap[i]+data[i]*window[i];
}else{
for(i=blocksize/2,j=0;i<blocksize;i++)
lap[j]=data[i]*window[i];
if(out)
for(i=0;i<blocksize/2;i++)
out[i]=data[i];
for(i=blocksize/2,j=0;i<blocksize;i++)
lap[j]=data[i]*window[i]*window[i];
}
}
/* called only by playback thread */
time_linkage *declip_read(time_linkage *in){
int i;
double work[blocksize];
double local_trigger[input_ch];
int total=0;
int count[input_ch];
time_linkage dummy;
double local_convergence;
double local_iterations;
pthread_mutex_lock(&master_mutex);
local_convergence=convergence;
local_iterations=iterations;
memcpy(local_trigger,chtrigger,sizeof(local_trigger));
pthread_mutex_unlock(&master_mutex);
memset(count,0,sizeof(count));
if(pending_blocksize!=blocksize){
if(blocksize){
......@@ -292,19 +353,19 @@ time_linkage *declip_read(time_linkage *in){
}
switch(fillstate){
case 0: /* prime the lapping and cache */
for(i=0;i<input_ch;i++){
int j;
double *temp=in->data[i];
if(chactive[i] && declip_active){
memset(work,0,sizeof(*work)*blocksize/2);
memcpy(work+blocksize/2,temp,sizeof(*work)*blocksize/2);
declip(work,lap[i],0,blocksize,chtrigger[i]);
}else{
for(j=0;j<blocksize/2;j++)
lap[i][j]=window[j+blocksize/2]*temp[j];
}
total=0;
memset(work,0,sizeof(*work)*blocksize/2);
memcpy(work+blocksize/2,temp,sizeof(*work)*blocksize/2);
declip(work,lap[i],0,blocksize,
local_trigger[i],local_convergence,local_iterations,
&total,count+i);
memset(cache[i],0,sizeof(**cache)*input_size);
in->data[i]=cache[i];
cache[i]=temp;
......@@ -317,20 +378,19 @@ time_linkage *declip_read(time_linkage *in){
case 1: /* nominal processing */
for(i=0;i<input_ch;i++){
double *temp=cache[i];
int j;
if(chactive[i] && declip_active){
for(j=0;j+blocksize<out.size;j+=blocksize/2){
memcpy(work,temp+j,sizeof(*work)*blocksize);
declip(work,lap[i],out.data[i]+j,blocksize,chtrigger[i]);
}
memcpy(work,temp+j,sizeof(*work)*blocksize/2);
memcpy(work+blocksize/2,in->data[i],sizeof(*work)*blocksize/2);
declip(work,lap[i],out.data[i]+j,blocksize,chtrigger[i]);
}else{
memcpy(out.data[i],temp,out.size*sizeof(*temp));
for(j=0;j<blocksize/2;j++)
lap[i][j]=window[j+blocksize/2]*temp[j];
int j;
total=0;
for(j=0;j+blocksize<out.size;j+=blocksize/2){
memcpy(work,temp+j,sizeof(*work)*blocksize);
declip(work,lap[i],out.data[i]+j,blocksize,
local_trigger[i],local_convergence,local_iterations,
&total,count+i);
}
memcpy(work,temp+j,sizeof(*work)*blocksize/2);
memcpy(work+blocksize/2,in->data[i],sizeof(*work)*blocksize/2);
declip(work,lap[i],out.data[i]+j,blocksize,
local_trigger[i],local_convergence,local_iterations,
&total,count+i);
in->data[i]=cache[i];
cache[i]=temp;
......@@ -342,5 +402,9 @@ time_linkage *declip_read(time_linkage *in){
case 2: /* we've pushed out EOF already */
return 0;
}
/* we're returning data, push feedback */
push_declip_feedback(count,total);
return &out;
}
......@@ -23,7 +23,8 @@
extern int declip_load(void);
extern int declip_setblock(int n);
extern int declip_setactive(int activep,int ch);
extern int declip_settrigger(double trigger,int ch);
extern int declip_setiterations(double x);
extern int declip_setconvergence(double x);
extern int declip_reset(void);
extern time_linkage *declip_read(time_linkage *in);
/*
*
* postfish
*
* Copyright (C) 2002-2004 Monty and Xiph.Org
*
* Postfish 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, or (at your option)
* any later version.
*
* Postfish 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 Postfish; see the file COPYING. If not, write to the
* Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*
*/
#include "postfish.h"
#include "feedback.h"
feedback_generic *feedback_new(feedback_generic_pool *pool,
feedback_generic *(*constructor)(void)){
feedback_generic *ret;
pthread_mutex_lock(&master_mutex);
if(pool->feedback_pool){
ret=pool->feedback_pool;
pool->feedback_pool=pool->feedback_pool->next;
pthread_mutex_unlock(&master_mutex);
return ret;
}
pthread_mutex_unlock(&master_mutex);
ret=constructor();
return ret;
}
void feedback_push(feedback_generic_pool *pool,
feedback_generic *f){
f->next=NULL;
pthread_mutex_lock(&master_mutex);
if(!pool->feedback_list_tail){
pool->feedback_list_tail=f;
pool->feedback_list_head=f;
}else{
pool->feedback_list_head->next=f;
pool->feedback_list_head=f;
}
pthread_mutex_unlock(&master_mutex);
}
feedback_generic *feedback_pull(feedback_generic_pool *pool){
feedback_generic *f;
pthread_mutex_lock(&master_mutex);
if(pool->feedback_list_tail){
f=pool->feedback_list_tail;
pool->feedback_list_tail=pool->feedback_list_tail->next;
if(!pool->feedback_list_tail)pool->feedback_list_head=0;
}else{
pthread_mutex_unlock(&master_mutex);
return 0;
}
pthread_mutex_unlock(&master_mutex);
return(f);
}
void feedback_old(feedback_generic_pool *pool,
feedback_generic *f){
pthread_mutex_lock(&master_mutex);
f->next=pool->feedback_pool;
pool->feedback_pool=f;
pthread_mutex_unlock(&master_mutex);
}
/*
*
* postfish
*
* Copyright (C) 2002-2004 Monty and Xiph.Org
*
* Postfish 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, or (at your option)
* any later version.
*
* Postfish 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 Postfish; see the file COPYING. If not, write to the
* Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*
*/
typedef struct feedback_generic{
struct feedback_generic *next;
} feedback_generic;
typedef struct feedback_generic_pool{
feedback_generic *feedback_list_head;
feedback_generic *feedback_list_tail;
feedback_generic *feedback_pool;
} feedback_generic_pool;
extern feedback_generic *feedback_new(feedback_generic_pool *pool,
feedback_generic *(*constructor)(void));
extern void feedback_push(feedback_generic_pool *pool,
feedback_generic *f);
extern feedback_generic *feedback_pull(feedback_generic_pool *pool);
extern void feedback_old(feedback_generic_pool *pool,
feedback_generic *f);
......@@ -2,7 +2,7 @@
*
* postfish
*
* Copyright (C) 2002-2003 Monty
* Copyright (C) 2002-2004 Monty
*
* Postfish is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -22,6 +22,7 @@
*/
#include "postfish.h"
#include "feedback.h"
#include "input.h"
static off_t Acursor=0;
......@@ -47,16 +48,13 @@ typedef struct {
} file_entry;
typedef struct input_feedback{
feedback_generic parent_class;
off_t cursor;
double *rms;
double *peak;
struct input_feedback *next;
} input_feedback;
static input_feedback *feedback_list_head;
static input_feedback *feedback_list_tail;
static input_feedback *feedback_pool;
static feedback_generic_pool feedpool;
static file_entry *file_list=NULL;
static int file_entries=0;
......@@ -163,7 +161,7 @@ void input_cursor_to_time(off_t cursor,char *t){
int input_load(int n,char *list[]){
char *fname="stdin";
int stdinp=0,i,j,ch,rate;
int stdinp=0,i,j,ch=0,rate=0;
off_t total=0;
if(n==0){
......@@ -309,7 +307,38 @@ int input_load(int n,char *list[]){
}
}
input_size=out.size=2048;
/* 192000: 8192
96000: 4096
88200: 4096
64000: 4096
48000: 2048
44100: 2048
32000: 1024
22050: 1024
16000: 1024
11025: 512
8000: 512
4000: 256 */
if(rate<6000){
input_size=out.size=256;
}else if(rate<15000){
input_size=out.size=512;
}else if(rate<25000){
input_size=out.size=1024;
}else if(rate<50000){
input_size=out.size=2048;
}else if(rate<100000){
input_size=out.size=4096;
}else
input_size=out.size=8192;
input_ch=out.channels=ch;
input_rate=out.rate=rate;
out.data=malloc(sizeof(*out.data)*ch);
......@@ -364,73 +393,31 @@ off_t input_time_seek_rel(double s){
return ret;
}
static input_feedback *new_input_feedback(void){
input_feedback *ret;
pthread_mutex_lock(&master_mutex);
if(feedback_pool){
ret=feedback_pool;
feedback_pool=feedback_pool->next;
pthread_mutex_unlock(&master_mutex);
return ret;
}
pthread_mutex_unlock(&master_mutex);
ret=malloc(sizeof(*ret));
static feedback_generic *new_input_feedback(void){
input_feedback *ret=malloc(sizeof(*ret));
ret->rms=malloc((input_ch+2)*sizeof(*ret->rms));
ret->peak=malloc((input_ch+2)*sizeof(*ret->peak));
return ret;
return (feedback_generic *)ret;
}
static void push_input_feedback(double *peak,double *rms, off_t cursor){
int i,n=input_ch+2;
input_feedback *f=new_input_feedback();
input_feedback *f=(input_feedback *)
feedback_new(&feedpool,new_input_feedback);
f->cursor=cursor;
memcpy(f->rms,rms,n*sizeof(*rms));
memcpy(f->peak,peak,n*sizeof(*peak));
f->next=NULL;
pthread_mutex_lock(&master_mutex);
if(!feedback_list_tail){
feedback_list_tail=f;
feedback_list_head=f;
}else{
feedback_list_head->next=f;
feedback_list_head=f;
}
pthread_mutex_unlock(&master_mutex);
feedback_push(&feedpool,(feedback_generic *)f);
}
int pull_input_feedback(double *peak,double *rms,off_t *cursor,int *nn){
input_feedback *f;
int pull_input_feedback(double *peak,double *rms,off_t *cursor){
input_feedback *f=(input_feedback *)feedback_pull(&feedpool);
int i,j,n=input_ch+2;
if(nn)*nn=n;
pthread_mutex_lock(&master_mutex);
if(feedback_list_tail){
f=feedback_list_tail;
feedback_list_tail=feedback_list_tail->next;
if(!feedback_list_tail)feedback_list_head=0;
}else{
pthread_mutex_unlock(&master_mutex);
return 0;
}
pthread_mutex_unlock(&master_mutex);
if(rms)
memcpy(rms,f->rms,sizeof(*rms)*n);
if(peak)
memcpy(peak,f->peak,sizeof(*peak)*n);
if(cursor)
*cursor=f->cursor;
pthread_mutex_lock(&master_mutex);
f->next=feedback_pool;
feedback_pool=f;
pthread_mutex_unlock(&master_mutex);
if(!f)return 0;
if(rms)memcpy(rms,f->rms,sizeof(*rms)*n);
if(peak)memcpy(peak,f->peak,sizeof(*peak)*n);
if(cursor)*cursor=f->cursor;
feedback_old(&feedpool,(feedback_generic *)f);
return 1;
}
......@@ -567,7 +554,7 @@ time_linkage *input_read(void){