⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sound_mixplay.c.svn-base

📁 A Flash Player with ActionScript support. Write in C and C++. It have two part, one is Player and an
💻 SVN-BASE
字号:
#include <stdio.h>#include <fcntl.h>#include <pthread.h>#include <assert.h>#include <sys/soundcard.h>#include <stdlib.h>#include "sound_mixplay_pub.h"#include "player_pub.h"#include <esd.h>extern player_t      *player_p;#define		SAMPLESIZE	16#define		DSP_SPEED	11025#define		MONO_STEREO	1		// 1 单声道, 2 立体声static void mix_data(struct pcm_block *bp,struct pcm_block *p);// 混音并播放void snd_mixplay_do(void) {    int			sound_fd = -1;					//声音设备的文件句柄    struct pcm_block 	buf;    struct channel	ch;    struct pcm_block	*bp = &buf;    struct pcm_block	*p;    struct pcm_block	*oldp;    int			states;    int			max_pos;#if 1    int rate = DSP_SPEED;    int bits = ESD_BITS16, channels = ESD_MONO;    int mode = ESD_STREAM, func = ESD_PLAY ;    char *host = "127.0.0.1:18000";    char *name = NULL;    esd_format_t format = 0;    sound_fd = esd_open_sound("127.0.0.1:18000");    format = bits | channels | mode | func;    sound_fd = esd_play_stream_fallback( format, rate, host, name );#else    int tmp;    int sample_size = SAMPLESIZE;    int dsp_speed = DSP_SPEED;    ch.sample_size = SAMPLESIZE;    ch.dsp_speed = DSP_SPEED;    ch.mono_stereo = MONO_STEREO;    buf.channel_p = &ch;    // 打开 dsp 文件    sound_fd = open("/dev/dsp", O_WRONLY, 0);    assert(sound_fd != -1);    // 设置采样长度    tmp = sample_size;    ioctl(sound_fd, SNDCTL_DSP_SAMPLESIZE, &sample_size);    assert(tmp == sample_size);    // 设置采样速率    tmp = ioctl(sound_fd, SNDCTL_DSP_SPEED, &dsp_speed);    assert(tmp != -1);#endif    while(1) {        states = pthread_mutex_lock(&player_p->pcm_block_mutex);        assert(states == 0);        p = player_p->pcm_block_head.downchannel_p;        memset(&buf,0,sizeof(struct pcm_block));        // 遍历所有 Channel.        // p 指向当前 Channel 的当前块. bp 指向播放缓冲区.        bp->pos = 0;        bp->length = BUF_LENGTH;        max_pos = 0;        while ( p != NULL ) {            // 如果缓冲区读满,则转下一通道            if (bp->pos == bp->length) {                p = p->downchannel_p;                bp->pos = 0;                continue;            };            // 如果当前块读完,并且下一块不为空,则当前块置为当前 Channel 的下一块            // ,并释放当前块.            if (( p->pos == p->length) && ( p->next_p != NULL)) {                oldp = p;                // 从双向链表中摘出去                if (p->upchannel_p != NULL) {                    p->upchannel_p->downchannel_p = p->next_p;                };                if (p->downchannel_p != NULL) {                    p->downchannel_p->upchannel_p = p->next_p;                };                p->next_p->upchannel_p = p->upchannel_p;                p->next_p->downchannel_p = p->downchannel_p;                p->next_p->channel_p = p->channel_p;		// Channel 指针传递下去                p = p->next_p;                free(oldp);                continue;            };            // 如果当前 channel 已读完            if (( p->pos == p->length) && ( p->next_p == NULL)) {                if (p->channel_p->type == STREAM_CHANNEL) {                    // 转下一通道                    p = p->downchannel_p;                    continue;                } else {                    // 如果 channel 不是 mp3 stream 型,则取消当前通道,并转下一通道                    oldp = p;                    if (p->upchannel_p != NULL) {                        p->upchannel_p->downchannel_p = p->downchannel_p;                    };                    if (p->downchannel_p != NULL) {                        p->downchannel_p->upchannel_p = p->upchannel_p;                    };                    p = p->downchannel_p;                    bp->pos = 0;                    // channel 释放时,同时释放附属的 channel 结构体.                    if (oldp->channel_p != NULL) {                        free(oldp->channel_p);                    };                    free(oldp);                    continue;                };            };            // 取一个采样到缓冲区            mix_data(bp,p);            if (bp->pos > max_pos) {                max_pos = bp->pos;            };        };        states = pthread_mutex_unlock(&player_p->pcm_block_mutex);        assert(states == 0);        // 如果遍历所有 channel 无收获,说明已无数据,休息 0.2s.        if (max_pos > 0) {            // 将播放缓冲区的内容送入声音设备            states = write(sound_fd,(bp->data),max_pos);            assert(states >= 0);        } else {            usleep(2000);        }    };}staticvoid mix_data(struct pcm_block *bp,struct pcm_block *p) {    int32_t 	s1,s2;    int8_t	conv;    int 	i;    //确定转换方案    conv = 0;    if ((p->channel_p->dsp_speed == DSP_SPEED) && ((p->channel_p->mono_stereo / MONO_STEREO) == 2) && ( p->channel_p->sample_size = 16)) {        conv = 2;    };    if (((p->channel_p->dsp_speed / DSP_SPEED) == 2) && (p->channel_p->mono_stereo == MONO_STEREO) && ( p->channel_p->sample_size = 16)) {        conv = 2;    };    if ((p->channel_p->dsp_speed == DSP_SPEED) && (p->channel_p->mono_stereo == MONO_STEREO) && ( p->channel_p->sample_size = 16)) {        conv = 3;    };    if (((p->channel_p->dsp_speed / DSP_SPEED) == 4) && (p->channel_p->mono_stereo == MONO_STEREO) && ( p->channel_p->sample_size = 16)) {        conv = 5;    };    if (((p->channel_p->dsp_speed / DSP_SPEED) == 4) && ((p->channel_p->mono_stereo / MONO_STEREO) == 2) && ( p->channel_p->sample_size = 16)) {        conv = 6;    };    if (((p->channel_p->dsp_speed / DSP_SPEED) == 2) && ((p->channel_p->mono_stereo / MONO_STEREO) == 2) && ( p->channel_p->sample_size = 16)) {        conv = 5;    };    //转换    switch(conv) {    case 2:        // 16 bit -> 16bit : 双声道->单声道 : 同速率        // 16 bit -> 16bit : 同声道 : 降一倍速率        while ((p->pos < p->length) && (bp->pos < bp->length)) {            s1 = *((SI16*)(p->data + p->pos));            p->pos = p->pos + 2;            assert(p->pos < p->length);            s2 = *((SI16*)(p->data + p->pos));            p->pos = p->pos + 2;            assert(p->pos <= p->length);            *((SI16*)(bp->data + bp->pos)) = *((SI16*)(bp->data + bp->pos)) + (s1+s2)/2/4;            bp->pos = bp->pos + 2;        };        break;    case 3:        // 16 bit -> 16bit : 同声道 : 同速率        while ((p->pos < p->length) && (bp->pos < bp->length)) {            *((SI16*)(bp->data + bp->pos)) = *((SI16*)(bp->data + bp->pos)) + *((SI16*)(p->data + p->pos))/4 ;            bp->pos = bp->pos + 2;            p->pos = p->pos + 2;        };        break;    case 4:        // 8 bit -> 8 bit : 同声道 : 同速率        *((SI8*)(bp->data + bp->pos)) = *((SI8*)(bp->data + bp->pos)) + *((SI8*)(p->data + p->pos))/4;        bp->pos = bp->pos + 1;        p->pos = p->pos + 1;        break;    case 5:        while ((p->pos < p->length) && (bp->pos < bp->length)) {            s1 = 0;            for (i=0;i<4;i++) {                if (!i) {                    s1=*((SI16*)(p->data + p->pos));                }                s1 += *((SI16*)(p->data + p->pos +i*2));            }            *((SI16*)(bp->data + bp->pos)) += (s1/16);            bp->pos = bp->pos + 2;            p->pos = p->pos + 8;        }        break;    case 6:        while ((p->pos < p->length) && (bp->pos < bp->length)) {            s1 = 0;            s2 = 0;            for (i=0;i<4;i++) {                if (!i) {                    s1=*((SI16*)(p->data + p->pos));                }                s1 += *((SI16*)(p->data + p->pos +i*2));            }            for (i=0;i<4;i++) {                if (!i) {                    s2=*((SI16*)(p->data + p->pos + 8));                }                s2 += *((SI16*)(p->data + p->pos +i*2 +8));            }            *((SI16*)(bp->data + bp->pos)) += (((s1/16)+(s1/16))/2);            bp->pos = bp->pos + 2;            p->pos = p->pos + 16;        }        break;    default:        assert(0);    };}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -