ADSP-21479的开发详解五(AD1939 C Block-Based Talkthru 48 or 96 kHz)音频直通

server/2024/9/25 21:28:06/

硬件准备

ADSP-21479EVB开发板:

产品链接:https://item.taobao.com/item.htm?id=555500952801&spm=a1z10.5-c.w4002-5192690539.11.151441a3Z16RLU

在这里插入图片描述

AD-HP530ICE仿真器:

产品链接:https://item.taobao.com/item.htm?id=38007242820&spm=a1z10.5-c.w4002-5192690539.11.59ae4901jeWaOn

软件准备

Visual DSP++5.1.2
CCES2.11.1

音频开发: 21479 AD1939 C Block-Based Talkthru 48 or 96 kHz(4 进 8 出)

这个程序,我们将会在开发板上实现 48Khz 或 96Khz 采样率的音频直通程序。原理上来 讲,手机或者 PC 的音源通过 1 分 2 音频线接入 21479 开发板的模拟输入接插件,将模拟音 频导入,通过 AD1938 进行模拟转数字,数字音频信号进入 21479 数字音频 DSP 中,不做任何处理,交给 AD1938 再进行数字转模拟,将模拟的音频信号送到对应的通道,实现多 通道输出。

硬件连接如下图:

在这里插入图片描述

在这里插入图片描述

为什么输入接 2/3 通道,输出接 2/3 通道(通道号在板子的背面的丝印),这是因为 程序就是这么写的的,我们来看看程序是怎么写的: 把工程拖入 VDSP 中,编译,运行,手机播放音源,输出到音响听到音乐,完成这个例程。

在这里插入图片描述

看看这个程序的 Readme,代码实现了 ADC 从 2/3 进,DAC 从 0/1 和 2/3 出。ADC 从 0/1 进,DAC 从 4/5 和 6/7 出。用户可以换一下输入输出接口,听一下效果。至于板子上哪个接 口是 0/1,哪个是 2/3?请看下图,红色的接插件是输入,2 个黑色的接插件是输出:

在这里插入图片描述

这个工程里,音频处理都在 DSP Audio Processing Routines 里,想要了解如何实现这种 直通,可以看里面的程序去理解。 程序里都有备注,比较容易看得懂,这里说的就是 4 进 8 出,1 左右声道进对应 12 左 右声道出,2 左右声道进对应 34 左右声道出。而 1 左右声道 IN 就是板子上的 0/1 IN,2 左右声道 IN 就是板子上的 2/3 IN。

核心代码分析

DSP

///
// //
// NAME: blockProcess_audio.c (Block-based Talkthrough) //
// DATE: 02/06/10 //
// PURPOSE: Process incoming AD1939 ADC data and prepare outgoing blocks for DAC. //
// //
// USAGE: This file contains the subroutines that float and fix the serial data, //
// and copy from the inputs to the outputs. //
// //
///

#include “ADDS_21479_EzKit.h”

// Define a structure to represent buffers for all 12 floating-point data channels of the AD1939
typedef struct{
float Rx_L1[NUM_SAMPLES];
float Rx_R1[NUM_SAMPLES];
float Rx_L2[NUM_SAMPLES];
float Rx_R2[NUM_SAMPLES];

float Tx_L1[NUM_SAMPLES];
float Tx_R1[NUM_SAMPLES];
float Tx_L2[NUM_SAMPLES];
float Tx_R2[NUM_SAMPLES];
float Tx_L3[NUM_SAMPLES];
float Tx_R3[NUM_SAMPLES];
float Tx_L4[NUM_SAMPLES];
float Tx_R4[NUM_SAMPLES];

} ad1939_float_data;

// SPORT Ping/Pong Data buffers
extern int TxBlock_A0[];
extern int TxBlock_A1[];

extern int RxBlock_A0[];
extern int RxBlock_A1[];

//Pointer to the blocks
int *rx_block_pointer[2] = {RxBlock_A0, RxBlock_A1};
int *tx_block_pointer[2] = {TxBlock_A0, TxBlock_A1};

// Structures to hold floating point data for each AD1939
ad1939_float_data fBlockA;

void process_audioBlocks(void);

// Unoptimized function to convert the incoming fixed-point data to 32-bit floating-point format.
// This function assumes that the incoming fixed point data is in 1.31 format
void floatData(float *output, int *input, unsigned int instep, unsigned int length)
{
int i;

for(i = 0; i < length; i++)
{output[i] = __builtin_conv_RtoF(input[instep*i]);
}

}

// Unoptimized function to convert the outgoing floating-point data to 1.31 fixed-point format.
void fixData(int *output, float *input, unsigned int outstep, unsigned int length)
{
int i;

for(i = 0; i < length; i++)
{output[outstep*i] = __builtin_conv_FtoR(input[i]);
}

}

// Unoptimized function to copy from one floating-point buffer to another
void memcopy(float *input, float *output, unsigned int number)
{
int i;

for(i = 0; i < number; i++)
{output[i] = input[i];
}

}

/
// Audio Block Processing Algorithm for 4 IN x 8 OUT Audio System

// The inputs and outputs are held in a structure for the AD1939
// fBlockA holds stereo input (AIN) channels 0-3 and stereo output (AOUT) channels 0-7

// This function copys the data without any processing as follows
// AOUT1L <- AIN1L
// AOUT1R <- AIN1R
// AOUT2L <- AIN1L
// AOUT2R <- AIN1R

// AOUT3L <- AIN2L
// AOUT3R <- AIN2R
// AOUT4L <- AIN2L
// AOUT4R <- AIN2R
/

void process_audioBlocks()
{
memcopy(fBlockA.Rx_L1, fBlockA.Tx_L1, NUM_SAMPLES);
memcopy(fBlockA.Rx_R1, fBlockA.Tx_R1, NUM_SAMPLES);
memcopy(fBlockA.Rx_L1, fBlockA.Tx_L2, NUM_SAMPLES);
memcopy(fBlockA.Rx_R1, fBlockA.Tx_R2, NUM_SAMPLES);
memcopy(fBlockA.Rx_L2, fBlockA.Tx_R3, NUM_SAMPLES);
memcopy(fBlockA.Rx_R2, fBlockA.Tx_L3, NUM_SAMPLES);
memcopy(fBlockA.Rx_L2, fBlockA.Tx_L4, NUM_SAMPLES);
memcopy(fBlockA.Rx_R2, fBlockA.Tx_R4, NUM_SAMPLES);
}

/
// This function handles the Codec data in the following 3 steps…
// 1. Converts all ADC data to 32-bit floating-point, and copies this
// from the current RX DMA buffer into fBlockA & fBlockB
// 2. Calls the audio processing function (processBlocks)
// 3. Converts all DAC to 1.31 fixed point, and copies this from
// fBlockA & fBlockB into the current TX DMA buffer
/

void handleCodecData(unsigned int blockIndex)
{
//Clear the Block Ready Semaphore
inputReady = 0;

//Set the Processing Active Semaphore before starting processing
isProcessing = 1;// Float ADC data from AD1939
floatData(fBlockA.Rx_L1, rx_block_pointer[blockIndex]+0, NUM_RX_SLOTS, NUM_SAMPLES);
floatData(fBlockA.Rx_R1, rx_block_pointer[blockIndex]+1, NUM_RX_SLOTS, NUM_SAMPLES);
floatData(fBlockA.Rx_L2, rx_block_pointer[blockIndex]+2, NUM_RX_SLOTS, NUM_SAMPLES);
floatData(fBlockA.Rx_R2, rx_block_pointer[blockIndex]+3, NUM_RX_SLOTS, NUM_SAMPLES);// Place the audio processing algorithm here. 
process_audioBlocks();// Fix DAC data for AD1939
fixData(tx_block_pointer[blockIndex]+0, fBlockA.Tx_L1, NUM_TX_SLOTS, NUM_SAMPLES);
fixData(tx_block_pointer[blockIndex]+1, fBlockA.Tx_R1, NUM_TX_SLOTS, NUM_SAMPLES);
fixData(tx_block_pointer[blockIndex]+2, fBlockA.Tx_L2, NUM_TX_SLOTS, NUM_SAMPLES);
fixData(tx_block_pointer[blockIndex]+3, fBlockA.Tx_R2, NUM_TX_SLOTS, NUM_SAMPLES);
fixData(tx_block_pointer[blockIndex]+4, fBlockA.Tx_L3, NUM_TX_SLOTS, NUM_SAMPLES);
fixData(tx_block_pointer[blockIndex]+5, fBlockA.Tx_R3, NUM_TX_SLOTS, NUM_SAMPLES);
fixData(tx_block_pointer[blockIndex]+6, fBlockA.Tx_L4, NUM_TX_SLOTS, NUM_SAMPLES);
fixData(tx_block_pointer[blockIndex]+7, fBlockA.Tx_R4, NUM_TX_SLOTS, NUM_SAMPLES);//Clear the Processing Active Semaphore after processing is complete
isProcessing = 0;

}

SPORT

///
//NAME: SPORT1_isr.c (Block-based Talkthrough)
//DATE: 02/06/10
//PURPOSE: Talkthrough framework for sending and receiving samples to the AD1939.
//
//USAGE: This file contains SPORT1 Interrupt Service Routine. Four buffers are used
// for this example: Two input buffers, and two output buffers.
///
/*
Here is the mapping between the SPORTS and the ADCs/DACs
For AD1939
ADC1 -> DSP : SPORT1A : TDM Channel 0,1
ADC2 -> DSP : SPORT1A : TDM Channel 2,3
DSP -> DAC1 : SPORT0A : TDM Channel 0,1
DSP -> DAC2 : SPORT0A : TDM Channel 2,3
DSP -> DAC3 : SPORT0A : TDM Channel 4,5
DSP -> DAC4 : SPORT0A : TDM Channel 6,7
*/

#include “ADDS_21479_EzKit.h”
#include <sru.h>

// Counter to choose which buffer to process
int buffer_cntr = 1;
// Semaphore to indicate to main that a block is ready for processing
int inputReady = 0;
// Semaphore to indicate to the isr that the processing has not completed before the
// buffer will be overwritten.
int isProcessing = 0;

//If the processing takes too long, the program will be stuck in this infinite loop.
void ProcessingTooLong(void)
{
while(1);
}

void TalkThroughISR(int sig_int)
{
int i;

if(isProcessing)ProcessingTooLong();//Increment the block pointer
buffer_cntr++;
buffer_cntr %= 2;
inputReady = 1;

}

MAIN

/

#include “ADDS_21479_EzKit.h”

void main()
{

initPLL_SDRAM(); //Initialize the PLL and SDRAM controller// Initialize DAI because the SPORT and SPI signals
// need to be routed
InitDAI();// This function will configure the AD1939 codec on the 21479 EZ-KIT
Init1939viaSPI();// Turn on SPORT0 TX and SPORT1 RX for Multichannel Operation
InitSPORT();// Unmask SPORT1 RX ISR Interrupt 
interrupt(SIG_SP1,TalkThroughISR);// Be in infinite loop and do nothing until done.
while(1)
{if(inputReady)handleCodecData(buffer_cntr);
}

}


http://www.ppmy.cn/server/5490.html

相关文章

OpenHarmony多媒体-mp3agic

简介 mp3agic 用于读取 mp3 文件和读取/操作 ID3 标签&#xff08;ID3v1 和 ID3v2.2 到 ID3v2.4&#xff09;,协助开发者处理繁琐的文件操作相关&#xff0c;多用于操作文件场景的业务应用。 效果展示&#xff1a; 下载安装 ohpm install ohos/mp3agicOpenHarmony ohpm环境配…

【Golang】Gin教学-获取请求信息并返回

安装Gin初始化Gin处理所有HTTP请求获取请求的URL和Method获取请求参数根据Content-Type判断请求数据类型处理JSON数据处理表单数据处理文件返回JSON响应启动服务完整代码测试 Gin是一个用Go&#xff08;又称Golang&#xff09;编写的HTTP Web框架&#xff0c;它具有高性能和简洁…

Spring 声明式事务控制

1. 编程式事务控制相关对象 1.1 PlatformTransactionManager PlatformTransactionManager 接口是 spring 的事务管理器&#xff0c;它提供了我们常用的操作事务的方法。 PlatformTransactionManager 是接口类型&#xff0c;不同的 Dao 层技术则有不同的实现类。例如:Dao层技…

Linux 下安装MySQL 5.7与 8.0详情

官网资源下载 1、检查 /tmp 临时目录权限&#xff0c;将 /tmp 目录及所有子目录和文件的权限设置为所有用户可读、写和执行 [rootlocalhost ~]# chmod -R 777 /tmp2、安装前检查相关依赖 2.1、查找是否安装了 libaio 包。libaio 是 Linux 下异步 I/O 库的一个实现&#xff0…

【设计模式】6、bridge 桥接模式

六、bridge 桥接模式 桥接设计模式 复杂逻辑拆分&#xff1a; 如果需要完成复杂的逻辑&#xff0c;可以把复杂逻辑设计为接口&#xff0c;内部再拆分为若干接口。这样复杂的逻辑会被拆分开&#xff0c;方便解耦。 例如&#xff1a;如果遥控器控制设备。可以遥控器设计为复杂…

【c++】vector的使用

&#x1f525;个人主页&#xff1a;Quitecoder &#x1f525;专栏&#xff1a;c笔记仓 朋友们大家好&#xff0c;我们本篇来到一个新的容器&#xff0c;vector的讲解和使用 目录 1.vector简单介绍2.vector的使用2.1构造函数2.2遍历vector2.3对容量操作2.4vector的增删查改 1.v…

Parade Series - CoreAudio Loopback

Scenario 鉴于业务场景需要&#xff0c; 经过技术路径探索&#xff0c; 发现 comtypes 兼容性过于混乱&#xff0c;故而考虑整合一个 CoreAudio 的轮子dll来解决实际问题&#xff01;std::StringStream ⇒ std::ios::binary ⇒ std::ofstream Loopback.dll #ifndef _DLL_C…

OpenHarmony实战开发-如何使用弹簧曲线实现抖动动画及手机振动效果案例。

介绍 本示例介绍使用vibrator.startVibration方法实现手机振动效果&#xff0c;用keyframeAnimateTo关键帧动画实现点击后的抖动动画。 效果图预览 使用说明 1.加载完成后显示登录界面&#xff0c;未勾选协议时点击一键登录按钮会触发手机振动效果和提示文本的抖动动画。 实…