OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 12357|回复: 12

DFF和DSF文件数据格式标准

[复制链接]

4

主题

43

帖子

1

精华

中级会员

Rank: 3Rank: 3

积分
390
金钱
390
注册时间
2016-9-4
在线时间
73 小时
发表于 2021-2-18 22:49:04 | 显示全部楼层 |阅读模式

1、硬件引脚连接(CS4398硬件解码DSD文件)
如果是使用没有SAI的stm32,传输dsd数据到dac芯片需要使用两个I2S,一个左声道,一个右声道。
其中第一个I2S包含全部的I2S传输所需要引脚,第二个I2S只要SDIN数据脚就行。
无标题.png
2、DFF音频数据处理(以DSD64为例,其他采用率应该原理相同)
DFF文件数据是一个左声道数据,然后紧接一个右声道数据。给DAC发送数据时,除了需要分开这两个声道的数据,还需要进行两个字节的大小端转换。比如左声道数据是0x64 0x45 0x12 0x32……那么必须调整为0x45 0x64 0x32 0x12 ……也就是两个两个数据进行对调。如果不进行对调的话会出现很明显的噪音!右声道数据也是一样的。
填充函数如下:
u32 dff_buffill(u8 *buf0,u8 *buf1,u16 size)
{
        u32 bread;
        u16 i;
        u8 *p;
          f_read(audiodev.file,audiodev.tbuf,size,(UINT*)&bread);        //先读取数据到总缓存
         //处理数据,将左右声道数据进行分离
          p=audiodev.tbuf;//先指向总缓存区域
          for(i=0;i<size/4;i++)
                {
                        //左声道数据
                        buf0[2*i]=p[4*i+2];
                        buf0[2*i+1]=p[4*i];
                        //右声道数据
                        buf1[2*i]=p[i*4+3];
                        buf1[2*i+1]=p[i*4+1];
                }
                if(bread<size)//不够数据了,补充0
                {
                        for(i=bread;i<(size-bread)/2;i++)
                        {
                                buf0=0;
                                buf1=0;
                        }
                }       
          return bread;
}

3、DSF文件音频数据的处理
(1)DSF文件与DFF不太一样,他是先左声道占据4096个数据,然后接下来的4096数据才是右声道数据,即4096个左声道数据,然后4096个数据。因此读取数据的缓存大小必须设置为8192的倍数。以保证能够读取完整的左右声道数据。
(2)与DFF文件音频数据一样也需要进行两个字节的大小端转换。
(3)除了需要两个字节的大小端转换,DSF音频数据本身还要按位进行转换,由LSB模式转换为MSB模式,前提是Bits per sample(Bits per sample具体在哪可以参考最后关于DSD文件解析参考资料)这个数是1,如果是8则不需要。
转换函数:
u8 LSB_MSB(u8 dat)
{
        u8 temp=0,i=0;
        for(i=0;i<7;i++)
        {
          temp|=dat&0x01;
                temp<<=1;
          dat>>=1;
        }
        temp|=dat&0x01;
        return temp;
}

(4)填充函数如下:其中SIZE我已经设置为16384,如果要取其他的数据,需要按8192的倍数进行修改
u32 dsf_buffill(u8 *buf0,u8 *buf1,u16 size)
{
        u32 bread;
        u16 i;
        u8 *p;
        f_read(audiodev.file,audiodev.tbuf,size,(UINT*)&bread);        //读取数据
        p=audiodev.tbuf;
          for(i=0;i<2048;i++)//前0~4095个是左声道数据
                {
                        buf0[2*i]=LSB_MSB(p[2*i+1]);
                        buf0[2*i+1]=LSB_MSB(p[2*i]);//转换数据
                }
                for(i=0;i<2048;i++)//4096~8191是右声道数据
                {
                        buf1[2*i]=LSB_MSB(p[2*i+1+4096]);
                        buf1[2*i+1]=LSB_MSB(p[2*i+4096]);//转换数据
                }
    for(i=2048;i<4096;i++)//8192~12287是左声道数据
                {
                        buf0[2*i]=LSB_MSB(p[2*i+1+4096]);
                        buf0[2*i+1]=LSB_MSB(p[2*i+4096]);//转换数据
                }
    for(i=2048;i<4096;i++)//12288-16383是右声道数据
                {
                        buf1[2*i]=LSB_MSB(p[2*i+1+8192]);
                        buf1[2*i+1]=LSB_MSB(p[2*i+8192]);//转换数据
                }

             if(bread<size)//不够数据了,补充0
                {
                        for(i=bread;i<(size-bread)/2;i++)
                        {
                                buf0=0;
                                buf1=0;
                        }
                }
        return bread;
}  

4、DSF、DFF、DST格式文件头部信息(采用率、文件大小、音频数据起始位置等等)解析,参考以下两个文件,结合wav文件的解析代码和winhex软件就可以很快搞定的。
DSFFileFormatSpec_E.pdf (46.33 KB, 下载次数: 23)
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

4

主题

43

帖子

1

精华

中级会员

Rank: 3Rank: 3

积分
390
金钱
390
注册时间
2016-9-4
在线时间
73 小时
 楼主| 发表于 2021-2-18 22:52:32 | 显示全部楼层
不知道为什么字体那么斜
回复 支持 反对

使用道具 举报

4

主题

43

帖子

1

精华

中级会员

Rank: 3Rank: 3

积分
390
金钱
390
注册时间
2016-9-4
在线时间
73 小时
 楼主| 发表于 2021-2-21 01:00:29 | 显示全部楼层
在处理DSD128时速度太慢会卡
改进转换算法稍微好一些
u8 LSB_MSB(u8 x)
{
          x = (((x & 0xaa) >> 1) | ((x & 0x55) << 1));  
    x = (((x & 0xcc) >> 2) | ((x & 0x33) << 2));  
    return((x >> 4) | (x << 4));  
}
回复 支持 反对

使用道具 举报

4

主题

43

帖子

1

精华

中级会员

Rank: 3Rank: 3

积分
390
金钱
390
注册时间
2016-9-4
在线时间
73 小时
 楼主| 发表于 2021-2-21 01:01:50 | 显示全部楼层
最快的方法查表,如果还不行,请加大读取缓存
const u8 BitReverseTable256[] =
{
        0X00,0x80,0x40,0xC0,0x20,0xA0,0x60,0xE0,0x10,0x90,0x50,0xD0,0x30,0xB0,0x70,0xF0,
        0x08,0x88,0x48,0xC8,0x28,0xA8,0x68,0xE8,0x18,0x98,0x58,0xD8,0x38,0xB8,0x78,0xF8,
        0x04,0x84,0x44,0xC4,0x24,0xA4,0x64,0xE4,0x14,0x94,0x54,0xD4,0x34,0xB4,0x74,0xF4,
        0x0C,0x8C,0x4C,0xCC,0x2C,0xAC,0x6C,0xEC,0x1C,0x9C,0x5C,0xDC,0x3C,0xBC,0x7C,0xFC,
        0x02,0x82,0x42,0xC2,0x22,0xA2,0x62,0xE2,0x12,0x92,0x52,0xD2,0x32,0xB2,0x72,0xF2,
        0x0A,0x8A,0x4A,0xCA,0x2A,0xAA,0x6A,0xEA,0x1A,0x9A,0x5A,0xDA,0x3A,0xBA,0x7A,0xFA,
        0x06,0x86,0x46,0xC6,0x26,0xA6,0x66,0xE6,0x16,0x96,0x56,0xD6,0x36,0xB6,0x76,0xF6,
        0x0E,0x8E,0x4E,0xCE,0x2E,0xAE,0x6E,0xEE,0x1E,0x9E,0x5E,0xDE,0x3E,0xBE,0x7E,0xFE,
        0x01,0x81,0x41,0xC1,0x21,0xA1,0x61,0xE1,0x11,0x91,0x51,0xD1,0x31,0xB1,0x71,0xF1,
        0x09,0x89,0x49,0xC9,0x29,0xA9,0x69,0xE9,0x19,0x99,0x59,0xD9,0x39,0xB9,0x79,0xF9,
        0x05,0x85,0x45,0xC5,0x25,0xA5,0x65,0xE5,0x15,0x95,0x55,0xD5,0x35,0xB5,0x75,0xF5,
        0x0D,0x8D,0x4D,0xCD,0x2D,0xAD,0x6D,0xED,0x1D,0x9D,0x5D,0xDD,0x3D,0xBD,0x7D,0xFD,
        0x03,0x83,0x43,0xC3,0x23,0xA3,0x63,0xE3,0x13,0x93,0x53,0xD3,0x33,0xB3,0x73,0xF3,
        0x0B,0x8B,0x4B,0xCB,0x2B,0xAB,0x6B,0xEB,0x1B,0x9B,0x5B,0xDB,0x3B,0xBB,0x7B,0xFB,
        0x07,0x87,0x47,0xC7,0x27,0xA7,0x67,0xE7,0x17,0x97,0x57,0xD7,0x37,0xB7,0x77,0xF7,
        0x0F,0x8F,0x4F,0xCF,0x2F,0xAF,0x6F,0xEF,0x1F,0x9F,0x5F,0xDF,0x3F,0xBF,0x7F,0xFF
};
u8 LSB_MSB(u8 x)
{
          return BitReverseTable256[x];
}
回复 支持 反对

使用道具 举报

4

主题

43

帖子

1

精华

中级会员

Rank: 3Rank: 3

积分
390
金钱
390
注册时间
2016-9-4
在线时间
73 小时
 楼主| 发表于 2021-2-21 09:08:58 | 显示全部楼层
dsf 的填充函数修改一下
u32 dsf_buffill(u8 *buf0,u8 *buf1,u16 size)
{
        u32 bread;
        u16 i;
        u8 *p;
         f_read(audiodev.file,audiodev.tbuf,size,(UINT*)&bread);        //读取数据
         
         for(i=0;i<2048;i++)//前0~4095个是左声道数据
                {
                        //左声道
                        p=audiodev.tbuf;
                        buf0[2*i]=LSB_MSB(p[2*i+1]);
                        buf0[2*i+1]=LSB_MSB(p[2*i]);//转换数据
                        p=audiodev.tbuf+8192;
                        buf0[2*i+4096]=LSB_MSB(p[2*i+1]);
                        buf0[2*i+1+4096]=LSB_MSB(p[2*i]);//转换数据
                        //右声道
                  p=audiodev.tbuf+4096;
                        buf1[2*i]=LSB_MSB(p[2*i+1]);
                        buf1[2*i+1]=LSB_MSB(p[2*i]);//转换数据
                        p=audiodev.tbuf+12288;
                        buf1[2*i+4096]=LSB_MSB(p[2*i+1]);
                        buf1[2*i+1+4096]=LSB_MSB(p[2*i]);//转换数据
                }
                if(bread<size)//不够数据了,补充0
                {
                        for(i=bread;i<(size-bread)/2;i++)
                        {
                                buf0[i]=0;
                                buf1[i]=0;
                        }
                }
        return bread;
}
回复 支持 反对

使用道具 举报

4

主题

43

帖子

1

精华

中级会员

Rank: 3Rank: 3

积分
390
金钱
390
注册时间
2016-9-4
在线时间
73 小时
 楼主| 发表于 2021-2-21 09:10:17 | 显示全部楼层
大小端转换太慢,最好采用查表方法
const u8 BitReverseTable256[] =
{
        0X00,0x80,0x40,0xC0,0x20,0xA0,0x60,0xE0,0x10,0x90,0x50,0xD0,0x30,0xB0,0x70,0xF0,
        0x08,0x88,0x48,0xC8,0x28,0xA8,0x68,0xE8,0x18,0x98,0x58,0xD8,0x38,0xB8,0x78,0xF8,
        0x04,0x84,0x44,0xC4,0x24,0xA4,0x64,0xE4,0x14,0x94,0x54,0xD4,0x34,0xB4,0x74,0xF4,
        0x0C,0x8C,0x4C,0xCC,0x2C,0xAC,0x6C,0xEC,0x1C,0x9C,0x5C,0xDC,0x3C,0xBC,0x7C,0xFC,
        0x02,0x82,0x42,0xC2,0x22,0xA2,0x62,0xE2,0x12,0x92,0x52,0xD2,0x32,0xB2,0x72,0xF2,
        0x0A,0x8A,0x4A,0xCA,0x2A,0xAA,0x6A,0xEA,0x1A,0x9A,0x5A,0xDA,0x3A,0xBA,0x7A,0xFA,
        0x06,0x86,0x46,0xC6,0x26,0xA6,0x66,0xE6,0x16,0x96,0x56,0xD6,0x36,0xB6,0x76,0xF6,
        0x0E,0x8E,0x4E,0xCE,0x2E,0xAE,0x6E,0xEE,0x1E,0x9E,0x5E,0xDE,0x3E,0xBE,0x7E,0xFE,
        0x01,0x81,0x41,0xC1,0x21,0xA1,0x61,0xE1,0x11,0x91,0x51,0xD1,0x31,0xB1,0x71,0xF1,
        0x09,0x89,0x49,0xC9,0x29,0xA9,0x69,0xE9,0x19,0x99,0x59,0xD9,0x39,0xB9,0x79,0xF9,
        0x05,0x85,0x45,0xC5,0x25,0xA5,0x65,0xE5,0x15,0x95,0x55,0xD5,0x35,0xB5,0x75,0xF5,
        0x0D,0x8D,0x4D,0xCD,0x2D,0xAD,0x6D,0xED,0x1D,0x9D,0x5D,0xDD,0x3D,0xBD,0x7D,0xFD,
        0x03,0x83,0x43,0xC3,0x23,0xA3,0x63,0xE3,0x13,0x93,0x53,0xD3,0x33,0xB3,0x73,0xF3,
        0x0B,0x8B,0x4B,0xCB,0x2B,0xAB,0x6B,0xEB,0x1B,0x9B,0x5B,0xDB,0x3B,0xBB,0x7B,0xFB,
        0x07,0x87,0x47,0xC7,0x27,0xA7,0x67,0xE7,0x17,0x97,0x57,0xD7,0x37,0xB7,0x77,0xF7,
        0x0F,0x8F,0x4F,0xCF,0x2F,0xAF,0x6F,0xEF,0x1F,0x9F,0x5F,0xDF,0x3F,0xBF,0x7F,0xFF
};
u8 LSB_MSB(u8 x)
{
          return BitReverseTable256[x];//查表方法
        //移位方法
         /* x = (((x & 0xaa) >> 1) | ((x & 0x55) << 1));  
    x = (((x & 0xcc) >> 2) | ((x & 0x33) << 2));  
    return((x >> 4) | (x << 4));  
        */
}
回复 支持 反对

使用道具 举报

4

主题

43

帖子

1

精华

中级会员

Rank: 3Rank: 3

积分
390
金钱
390
注册时间
2016-9-4
在线时间
73 小时
 楼主| 发表于 2021-2-21 09:44:12 | 显示全部楼层

硬解DSF64/128和DSD64/128代码
STM32F405RGT6+CS4398
链接:https://pan.baidu.com/s/1WoYCC3_ph2_bTxHpjXqyfA
提取码:wzqh
回复 支持 反对

使用道具 举报

0

主题

7

帖子

0

精华

新手入门

积分
17
金钱
17
注册时间
2020-9-6
在线时间
2 小时
发表于 2021-4-4 22:47:36 | 显示全部楼层
感谢楼主无私奉献啊!
回复 支持 反对

使用道具 举报

4

主题

43

帖子

1

精华

中级会员

Rank: 3Rank: 3

积分
390
金钱
390
注册时间
2016-9-4
在线时间
73 小时
 楼主| 发表于 2021-4-13 11:05:32 | 显示全部楼层
提醒一下,有些f4芯片是有I2S4/5的。如果使用了I2S4/5而参数设置还是按照I2S1/2/3,那么时钟速度会是I2S1/2/3的8倍,因此必须减小8倍才能正常使用。另外I2S4还是5来着没有MCLK输出引脚,要特别注意,最好不要用来作为主时钟输出
回复 支持 反对

使用道具 举报

3

主题

7

帖子

0

精华

新手上路

积分
48
金钱
48
注册时间
2020-7-11
在线时间
17 小时
发表于 2022-12-14 17:16:30 | 显示全部楼层
楼主好:原子的探索板能否解析dff和dsf我解析出来都是噪音?
回复 支持 反对

使用道具 举报

0

主题

3

帖子

0

精华

新手入门

积分
19
金钱
19
注册时间
2023-8-19
在线时间
5 小时
发表于 2024-2-4 04:05:07 来自手机 | 显示全部楼层
风之伤544 发表于 2021-4-13 11:05
提醒一下,有些f4芯片是有I2S4/5的。如果使用了I2S4/5而参数设置还是按照I2S1/2/3,那么时钟速度会是I2S1/2 ...

厉害了,我让朋友多研究一下
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-5-14 08:53

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表