/* # # ivtv PCM output level/sample.freq diagnostic tool # # Copyright (C) 2006 Maksym Veremeyenko (verem@m1stereo.tv) # # 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. # http://www.gnu.org/copyleft/gpl.html # */ #include #include /* Uses _GNU_SOURCE to define getsubopt in stdlib.h */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define SAMPLES_CNT (48000 / 10) #define DB_MAX 50 union { char bytes[4]; struct { long left:16; long right:16; } words; } __attribute__((packed)) audio_sample; void print_usage(void) { printf("Usage:\n\tivtv-pcm-tester \n"); }; int main(int argc, char **argv) { int fd; int i; char line[DB_MAX + 1]; line[DB_MAX] = 0; if (argc != 2) { fprintf(stderr, "Error, incorrect arguments!\n"); print_usage(); exit(-1); } fd = open(argv[1], O_RDONLY); if (fd == -1) { fprintf(stderr, "Error, unable to open device '%s'\n", argv[1]); exit(-1); } printf(" -50 -45 -40 -35 -30 -25 -20 -15 -10 -5 0\n" " Freq Level|....|....|....|....|....|....|....|....|....|....|!\n"); while (1) { struct timeval t1, t2; double peakl_max = 0.0, peakl_min = 65536.0; double peakr_max = 0.0, peakr_min = 65536.0; double period, f; /* fix time */ gettimeofday(&t1, NULL); /* read samples and find peaks */ for (i = 0; i < SAMPLES_CNT; i++) { /* read sample */ if (read(fd, &audio_sample, sizeof(audio_sample))) { double current = (double)audio_sample.words.left; if (peakl_max < current) peakl_max = current; if (peakl_min > current) peakl_min = current; current = (double)audio_sample.words.right; if (peakr_max < current) peakr_max = current; if (peakr_min > current) peakr_min = current; } else { printf("\n"); close(fd); exit(0); } } /* fix time */ gettimeofday(&t2, NULL); /* calc time */ period = (double)(t2.tv_sec - t1.tv_sec) + (double)(t2.tv_usec - t1.tv_usec) / 1000000.0; /* calc freq */ f = (period == 0.0) ? 0 : ((double)SAMPLES_CNT) / period; /* calc level */ double l = 20.0 * log((peakl_max - peakl_min) / 65536.0) / log(10.0); double r = 20.0 * log((peakr_max - peakr_min) / 65536.0) / log(10.0); /* create line */ for (i = 0; i < DB_MAX; i++) { line[i] = ' '; if (i - DB_MAX < l && i - DB_MAX < r) line[i] = '='; else if (i - DB_MAX < l) line[i] = 'l'; else if (i - DB_MAX < r) line[i] = 'r'; } /* output result */ printf("|%7.0lf| %7.3lf|%s\r", f, l, line); fflush(stdout); } }