📄 oss_dsp.c
字号:
/** /dev/dsp driver*//** This code is taken from tonegen program.* ToneGen: Plays a sine wave via the dsp or standard out. ToneGen written by Timothy Pozar pozar@lns.com*/#include <stdio.h>#include <stdlib.h>#include <fcntl.h>#include <sys/ioctl.h>#include <math.h>#include <unistd.h>#include <pthread.h>#include <linux/soundcard.h>#define DSPDEV "/dev/dsp"#define TRUE 1#define FALSE 0#define TSIZE 4096static unsigned char *audio_buffer;static int rate = 44100;static int gotmask;static int oss_h;static int oss_init = 0;static char device[TSIZE];static pthread_t backg_tid;volatile int audio_lock = 0;struct oss_qe_s { int freq; int time; int vol; };typedef struct oss_qe_s oss_node;#define QSIZE 4096static oss_node audio_queue[QSIZE];static int q_head, q_tail;void* ossdsp_backg(void*);/**/int ossdsp_init(){ strcpy(device, DSPDEV); if ( (oss_h = open(device, O_RDWR)) == -1 ) { perror("oss: opening device"); return 0; } else { if ( ioctl(oss_h, SNDCTL_DSP_GETFMTS, &gotmask) == -1 ) { perror("oss: get dsp mask"); return 0; } if ( ioctl(oss_h, SNDCTL_DSP_SPEED, &rate) == -1){ perror("oss: set sample rate"); return 0; } } audio_buffer = (unsigned char *) malloc((rate << 1)); q_head = q_tail = 0; oss_init = 1; if ( pthread_create(&backg_tid, NULL, ossdsp_backg, NULL) ) { perror("oss: background thread failed"); oss_init = 0; return 0; } return 1;}/**/void ossdsp_close(){ if ( oss_init ) { oss_init = 0; usleep(1000); close(oss_h); oss_h = -1; free(audio_buffer); }}/**/void ossdsp_play(int freq, int time_ms, int vol){ int count, loops; double cyclesamples; double f, sinnum, fu; short int dspnum; if ( !freq ) freq = rate >> 1; cyclesamples = ((double) rate) / ((double) freq); loops = (time_ms * freq/2) / 1000; memset(audio_buffer, 0x7f, rate << 1); fu = (2.0 * M_PI) / cyclesamples; f = fu; count = 0; while ( 1 ) { sinnum = sin(f); dspnum = 0x7fff * sinnum; memmove(audio_buffer + count, &dspnum, sizeof(dspnum)); count += sizeof(dspnum); write(oss_h, audio_buffer, count); count = 0; f += fu; if ( f > (2.0 * M_PI) ) { loops --; if ( loops <= 0 ) return; f = fu; } }}/**/void* ossdsp_backg(void *nil){ oss_node *node; while ( 1 ) { if ( oss_init ) { if ( !audio_lock ) { if ( q_head != q_tail ) { while ( q_head != q_tail ) { node = &audio_queue[q_head]; ossdsp_play(node->freq, node->time, node->vol); q_head ++; if ( q_head == QSIZE ) q_head = 0; } } else usleep(1000); // sleep 1ms, wait for message } else usleep(100); // sleep 0.1 ms, locked } else usleep(1000000); } return NULL;}/**/void oss_sound(int frq, int ms, int vol, int bgplay){ oss_node *node; int q_next; if ( oss_init ) { node = &audio_queue[q_tail]; node->freq = frq; node->time = ms; node->vol = vol; audio_lock = 1; q_tail ++; if ( q_tail == QSIZE ) q_tail = 0; audio_lock = 0; if ( !bgplay ) usleep(ms * 1000); }}/**/void oss_beep(){ oss_sound(440, 250, 75, 0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -