糖果派对官方网站_可以赌钱的糖果游戏_手机版
最简便易行的视音频播放示例9:SDL2播放PCM

最简便易行的视音频播放示例9:SDL2播放PCM

作者:操作系统    来源:未知    发布时间:2020-03-20 15:56    浏览量:

作者是信守那几个博客上面来做的魔法要求自己三只获取数据一边播放,现在播报什么的都平日,然则境遇二个老大临时才会并发的BUGBUG:不经常候播放过无数首音乐后会形成噪音输出,有的时候候刚播放第一首一有的后也会成为噪音输出,等那首音乐广播完,播放下一首又会变健康了,反正很有时现身那个BUG,平常情况下不也许再次出现这些BUG。可是在debug方式下在MyDevice::readData(char*data,qint64maxlen卡塔尔中打断点,然后去掉断点继续播放,多来三次也会成为噪音,data_pcm中一定会将是有数据的,如若再持续打断点去掉断点操作三次又产生正规音乐广播了,不明了是怎么原因?有没有大神扶助看看那几个难点重写QIODevice类中readData函数,data_pcm为音频数据,memcpy到声卡缓存中qint64MyDevice::readData(char*data,qint64maxlenState of Qatar//data为声卡的多寡缓冲区地址,maxlen为声卡缓冲区最大能寄存的字节数{if(len_written=data_pcm.size(卡塔尔(قطر‎卡塔尔国return0;intlen;//计算未播放的多少的尺寸len=(len_written+maxlen)data_pcm.size()?(data_pcm.size()-len_written):maxlen;memcpy(data,data_pcm.data()+len_最简便易行的视音频播放示例9:SDL2播放PCM。written,len卡塔尔(قطر‎;//把要播放的pcm数据存入声卡缓冲区里len_written+=len;//更新已播放的数额长度returnlen;}

正文记录SDL播放音频的本事。在那处运用的版本是SDL2。实际上SDL本身并不提供视音频播放的功能,它只是包裹了视音频播放的尾巴部分API。在Windows平台下,SDL封装了Direct3D这类的API用于广播摄像;封装了DirectSound那类的API用于广播音频。因为SDL的编纂指标正是简化视音频播放的付出难度,所以使用SDL播放录像(YUV/LacrosseGB)和节奏(PCM)数据十分的轻易。

动用无锁队列(环形缓冲区)注意事项,队列环形

环形缓冲区是临盆者和买主模型中常用的数据布局。分娩者将数据放入数组的尾端,而消费者从数组的另一端移走多少,当达到数组的尾部时,分娩者绕回到数组的底部。假诺独有一个劳动者和叁个买主,那么就足以做到免锁访谈环形缓冲区(Ring Buffer)。写入索引只允许临蓐者访谈并校正,只要写入者在立异索引以前将新的值保存到缓冲区中,则读者将始终见到同一的数据构造。同理,读取索引也只允许客商访谈并改善。

环形缓冲区完成原理图

                       bb电子糖果派对 1

如图所示,当读者和写者指针相等时,注脚缓冲区是空的,而只要写入指针在读取指针前边时,注解缓冲区已满。

清单 9. 2.6.10 环形缓冲区完结代码

 /*

 * __kfifo_put - puts some data into the FIFO, no locking version

 * Note that with only one concurrent reader and one concurrent

 * writer, you don't need extra locking to use these functions.

 */

 unsigned int __kfifo_put(struct kfifo *fifo,

       unsigned char *buffer, unsigned int len)

 {

  unsigned int l;

  len = min(len, fifo->size - fifo->in + fifo->out);

  /* first put the data starting from fifo->in to buffer end */

  l = min(len, fifo->size - (fifo->in & (fifo->size - 1)));

  memcpy(fifo->buffer + (fifo->in & (fifo->size - 1)), buffer, l);

  /* then put the rest (if any) at the beginning of the buffer */

  memcpy(fifo->buffer, buffer + l, len - l);

  fifo->in += len;

  return len;

 }

 

 /*

 * __kfifo_get - gets some data from the FIFO, no locking version

 * Note that with only one concurrent reader and one concurrent

 * writer, you don't need extra locking to use these functions.

 */

 unsigned int __kfifo_get(struct kfifo *fifo,

     unsigned char *buffer, unsigned int len)

 {

  unsigned int l;

  len = min(len, fifo->in - fifo->out);

  /* first get the data from fifo->out until the end of the buffer */

  l = min(len, fifo->size - (fifo->out & (fifo->size - 1)));

  memcpy(buffer, fifo->buffer + (fifo->out & (fifo->size - 1)), l);

  /* then get the rest (if any) from the beginning of the buffer */

  memcpy(buffer + l, fifo->buffer, len - l);

  fifo->out += len;

  return len;

 }

 

内需静心的是

使用ring_buffer_get(kfifo_get)或者ring_buffer_put(kfifo_put)时,倘使回到参数与传播参数len不对等时,则操作失利

 

大家定义贰个

//注意student_info 共17字节 根据内部存款和储蓄器排列占24字节

typedef struct student_info

{

    uint64_t stu_id; //8个字节

    uint32_t age;  //4字节

    uint32_t score;//4字节

     char sex;//1字节

}student_info;

 

我们创造三个环形缓冲区,里面唯有64字节大小(即便大家实际利用时大小远不唯有此),向里面频频存入24字节student_info,看有啥反应

 

//打字与印刷学子消息

void print_student_info(const student_info *stu_info)

{

    assert(stu_info);

    printf("id:%lut",stu_info->stu_id);

    printf("age:%ut",stu_info->age);

     printf("sex:%dt",stu_info->sex);

    printf("score:%un",stu_info->score);

}

 

student_info * get_student_info(time_t timer)

{

    student_info *stu_info = (student_info *)malloc(sizeof(student_info));

    srand(timer);

    stu_info->stu_id = 10000 + rand() % 9999;

    stu_info->age = rand() % 30;

    stu_info->score = rand() % 101;

     stu_info->sex=rand() % 2;

    print_student_info(stu_info);

    return stu_info;

}

void print_ring_buffer_len(struct ring_buffer *ring_buf)

{

     //用于打字与印刷缓冲村长度

     uint32_t ring_buf_len = 0;

     //获得已经应用缓冲村长度 size-ring_buf_len为未利用缓冲区的尺寸

     ring_buf_len=ring_buffer_len(ring_buf);

     printf("no use ring_buf_len:%dn",(ring_buf->size-ring_buf_len));

}

int main(int argc, char *argv[])

{

    uint32_t size = 0;

     //用于判定存储可能得到数据的字节数

     uint32_t oklen = 0;

    struct ring_buffer *ring_buf = NULL;

    //64字节

    size=BUFFER_SIZE;

    ring_buf = ring_buffer_alloc(size);

     printf("input studentn");

     {

         student_info *stu_info;

         student_info stu_temp;

         uint32_t student_len=sizeof(student_info);

         printf("ring_buf_len:%dn",ring_buf->size);

         printf("student_len:%dn",student_len);

         //那个时候环形缓冲区不多大家去取数据当然为空

         memset(&stu_temp,0,student_len);

         oklen=ring_buffer_get(ring_buf, (void *)(&stu_temp), student_len);

         if(oklen==student_len)

         {

            printf("get student datan");

         }

         else

         {

            printf("no student datan");

         }

         printf("n");

        //第一遍调用时用字节甘休后还应该有64-24 =40字节

         stu_info = get_student_info(976686458);

         oklen = ring_buffer_put(ring_buf, (void *)stu_info, student_len);

         if(oklen==student_len)

         {

           printf("1 put student data successn");

         }

         else

         {

            printf("1 put student data failuren");

         }

         print_ring_buffer_len(ring_buf);

 

         printf("n");

         //第壹回调用时用字节结束后还会有64-48 =16字节

         stu_info = get_student_info(976686464);

         oklen= ring_buffer_bb电子糖果派对,put(ring_buf, (void *)stu_info, student_len);

         if(oklen==student_len)

         {

           printf("2 put student data successn");

         }

         else

         {

            printf("2 put student data failuren");

         }

         print_ring_buffer_len(ring_buf);

 

         printf("n");

         //第三回调用时要求用字节但独有字节退步

         //把字节都写满了

        //验证了在调用__kfifo_put函数大概__kfifo_get函数时,假诺回去参数与传播参数len不对等时,则操作失利

         stu_info = get_student_info(976686445);

         oklen= ring_buffer_put(ring_buf, (void *)stu_info, student_len);

         if(oklen==student_len)

         {

           printf("3 put student data successn");

         }

         else

         {

            printf("3 put student data failuren");

         }

         print_ring_buffer_len(ring_buf);

       

         printf("n");

         //第五遍调用时须要用字节但无字节

         ////验证了在调用__kfifo_put函数可能__kfifo_get函数时,假设回到参数与传播参数len不等于时,则操作退步

         stu_info = get_student_info(976686421);

         oklen= ring_buffer_put(ring_buf, (void *)stu_info, student_len);

         if(oklen==student_len)

         {

           printf("4 put student data successn");

         }

         else

         {

            printf("4 put student data failuren");

         }

         print_ring_buffer_len(ring_buf);

 

         printf("n");

         //以后初阶取学子数量之中保存了个学子数量大家取壹遍看效用

         printf("output studentn");

 

         printf("n");

         //第叁遍得到数据并打字与印刷

         memset(stu_info,0,student_len);

          oklen=ring_buffer_get(ring_buf, (void *)stu_info, student_len);

         if(oklen==student_len)

         {

            print_student_info(stu_info);

           printf("1 get student data successn");

         }

         else

         {

            printf("1 get student data failuren");

         }

         print_ring_buffer_len(ring_buf);

 

         printf("n");

         ////第三回获得数据并打字与印刷

         memset(stu_info,0,student_len);

          oklen=ring_buffer_get(ring_buf, (void *)stu_info, student_len);

         if(oklen==student_len)

         {

            print_student_info(stu_info);

           printf("2 get student data successn");

         }

         else

         {

            printf("2 get student data failuren");

         }

         print_ring_buffer_len(ring_buf);

 

         printf("n");

        //第一遍取得数据退步

         memset(stu_info,0,student_len);

         oklen=ring_buffer_get(ring_buf, (void *)stu_info, student_len);

         if(oklen==student_len)

         {

            print_student_info(stu_info);

           printf("3 get student data successn");

         }

         else

         {

             printf("3 get student data failuren");

         }

         print_ring_buffer_len(ring_buf);

 

     }

 

     return 1;

}

     bb电子糖果派对 2

 

结论:在使用ring_buffer_get(kfifo_get)或者ring_buffer_put(kfifo_put)时,假如回去参数与传播参数len不等于时,则操作退步。代码下载:tessc.rar(

亟待注意的地点:

1.唯有三个线程担负读,另二个线程担当写的时候,数据是线程安全的。上面包车型大巴落实是依附那一个原理实现的,当有五个线程读也许八个线程写的时候,不保险数据的正确性。
于是利用的时候,二个线程写,一个线程读。网络使用中比较常用,正是开一个线程接口数据,然后把数据写入队列。然后开二个调整线程读取互联网数据,然后分发随处理线程。

2.数目长度暗许宏定义了贰个长短,超越那个长度的时候,后续的数据会写入退步。

正文参照他事他说加以考查小说:

 

 

bb电子糖果派对 3

环形缓冲区是哪一类缓冲区

应当归于队列把,循环队列  

SDL简介

SDL(Simple DirectMedia Layer)是一套开放源代码的跨平台多媒体开拓库,使用C语言写成。SDL提供了数种调节图像、声音、输出入的函数,让开拓者只要用同一也许雷同的代码就足以付出出跨七个阳台(Linux、Windows、Mac OS X等)的使用软件。近期SDL多用来开垦娱乐、模拟器、媒体播放器等多媒体应用领域。用上面那张图能够很明朗地说明SDL的用场。

 bb电子糖果派对 4

SDL实际上并不压迫视音频的播音,它将效率分成下列数身形系统(subsystem):

Video(图像):图像调整以至线程(thread)和事件处理(event)。

奥迪(AudiState of Qataro(声音):声音调整

Joystick(摇杆):游戏摇杆调控

CD-ROM(光盘驱动器):光盘媒体调节

Window Management(视窗处理):与视窗程序设计集成

伊芙nt(事件驱动):处管事人件驱动

在Windows下,SDL与DirectX的照管关系如下。

SDL

DirectX

SDL_Video、SDL_Image

DirectDraw、Direct3D

SDL_Audio、SDL_Mixer

DirectSound

SDL_Joystick、SDL_Base

DirectInput

SDL_Net

DirectPlay

注:上文内容在《使用SDL播放录像》的小说中早就介绍,这里再一次重复贴一次。

出于系统缓冲区空间欠缺或队列已满,不得以进行套接字上的操作(1005卡塔尔(قطر‎,ON API 'connenct

设置一下 最大磁盘缓存 的址吧。
只要内部存款和储蓄器够的话弄大学一年级些  

环形缓冲区是劳动者和买主模型中常用的数据构造。生产者将数据放入数组的尾端,而...

友情链接: 网站地图
Copyright © 2015-2019 http://www.tk-web.com. bb电子糖果派对有限公司 版权所有