使用librosa展示音乐中多个八度的详细音高时长图谱

使用librosa展示音乐中多个八度的详细音高时长图谱
示例中使用了7个八度的音高范围以及钢琴中间的3个八度录音

import matplotlib.pyplot as plt
import librosa
import numpy as np
import pandas as pd
# 读取音频文件
audio_file = 'C://Users//roben//Desktop//wavMID/3-8.wav'
y, sr = librosa.load(audio_file)

# 提取音高
pitches, magnitudes = librosa.piptrack(y=y, sr=22050, S=None, n_fft=4096, hop_length=None, fmin=27.5, fmax=4186.0, 
                                       threshold=0.9999, win_length=None, window='hann', center=True, pad_mode='constant', ref=None)
print(pitches.shape)
df=pd.DataFrame(pitches)
print(df.shape)
# df=df.drop(df.index[(df == 0).all(axis=1)])
# print(df.shape)

#音高转化为音符
df=df.applymap(lambda x: librosa.hz_to_note(x) if x>0 else 0)
#print(df)
#df.to_excel("C://Users//roben//Desktop//ccc.xlsx", encoding='gbk')

 #生成7个八度的index_list
list0 =["C","C♯","D","D♯","E","F","F♯","G","G♯","A","A♯","B"]
index_list=[]
for i in range(1,8):
    index_list=index_list+[ x+str(i) for x in list0]
print(index_list)

#音符转化为显示序列
df=df.applymap(lambda x: index_list.index(x)+1 if x in index_list else 0)
#print(df)
#df.to_excel("C://Users//roben//Desktop//index.xlsx", encoding='gbk')
#提取音符显示序列
ones= np.ones(df.shape[0])
print(ones.shape)
note_values=ones.dot(df)
print(note_values)

#展示音高与时长图谱
plt.figure(figsize=(20,20))
plt.xlabel('time')
plt.ylabel('notes')
plt.grid(linewidth=0.5,alpha=0.5)
plt.xticks(range(0,df.shape[1],20))
plt.yticks(range(1,len(index_list)+1),index_list)
plt.plot(note_values,color="#008080",linewidth=0.8)
plt.hlines(note_values, np.array(range(len(note_values)))-0.5,np.array(range(len(note_values)))+0.5,color="red", linewidth=5)
plt.show()

请添加图片描述

<think>首先,用户的问题是关于“多个IIC从机的pad中output_enable合并的方法”。用户提到想查找多个IIC从机的pad中的output_enable合并的方法。 回顾引用内容: - 引用[1]:描述了三态门的控制方法,使用assign语句来实现输出和输入的控制。关键点是当控制信号为高时输出数据,为低时输入数据。 - 引用[2]:讨论了I2C仲裁机制,如果仲裁丢失,切换到从模式。 - 引用[3]:解释了IO和GPIO的区别,以及GPIO的基本结构。 用户的问题焦点是多个IIC从机的output_enable信号的合并。output_enable通常用于控制三态门的输出使能,决定IO口是输出数据还是高阻状态。 在I2C通信中,SDA线是开漏或集电极开路结构,允许多个设备共享同一条线。多个从机共享SDA线时,output_enable信号需要正确处理以避免冲突。 核心概念: - 在I2C中,多个从机可以连接到同一个SDA线上。仲裁机制确保只有一个设备驱动线路。 - output_enable信号控制何时设备驱动线路(输出低电平,因为是开漏)。 合并多个从机的output_enable的方法: - 由于I2C是多主或多从协议,output_enable应该基于设备状态驱动。 - 一种常见方法是使用逻辑门(如AND或OR)来合并output_enable信号,但需要小心确保不冲突。 从引用[1]来看,它展示了如何用Verilog assign语句控制三态门: - `assign io_iic_sda = r_iic_sda_ctrl ? ro_iic_sda : 1'bz;` // 输出数据或高阻 - `assign w_iic_sda = !r_iic_sda_ctrl ? io_iic_sda : 1'b0;` // 读取输入数据 对于多个设备,output_enable信号需要合并以共享同一个SDA线。 可能的合并方法: 1. **使用开漏结构**:在硬件上,I2C设备通常使用开漏输出,这意味着它们只能拉低线路,不能主动驱动高电平。高电平由上拉电阻提供。因此,多个output_enable信号可以“线与”:如果任何设备输出低,线路被拉低;否则保持高。 - output_enable通常直接控制是否驱动低电平。 - 在实际合并中,不需要复杂的逻辑;只需确保当一个设备输出数据时,其他设备输出高阻。 2. **在FPGA或逻辑设计中合并**: - 对于多个从机,每个从机有自己的output_enable信号。 - 合并方法:SDA线应该是所有从机SDA输出的“线与”。如果用Verilog实现,可以这样: - 定义一个wire用于SDA线。 - 每个从机贡献其输出,但当output_enable为false时输出高阻。 - 例如:`assign sda = (output_enable1) ? data1 : 1'bz;` 类似地定义多个。 - 然后,整个总线:`wire sda_bus = sda_device1 & sda_device2 & ... ;` 但由于是开漏,在Verilog中通常模拟为: - `assign sda = (output_enable1) ? data1 : 1'bz;` - `assign sda = (output_enable2) ? data2 : 1'bz;` // 但Verilog中不能多个assign到同一个wire,需使用其他方式。 - 正确方法是使用`tri`类型或结合多个源。 更具体的合并方法: - 在硬件描述语言中,如Verilog,可以使用三态总线。 - 示例代码: ```verilog wire sda; assign sda = (output_enable1) ? data1 : 1'bz; assign sda = (output_enable2) ? data2 : 1'bz; // ... ``` 但Verilog不允许多个assign到同一个wire;需要使用`wire [N:0] sda_sources`或其他技巧。实际上,可以定义一个tri-state bus。 - 更好的方式:所有设备共享一个SDA线,每个设备当output_enable高时驱动其data,否则高阻。 - 仲裁由硬件处理:如果多个设备同时驱动,冲突发生,但I2C协议有仲裁机制(引用[2])。 用户问“合并的方法”,可能指的是如何逻辑上或代码中合并多个output_enable信号。 通用方法: - 对于多个从机,output_enable信号应该独立控制,但SDA线是共享的。 - 当任何设备要输出时,它设置自己的output_enable高,但如果多个设备驱动同一时间,仲裁会解决(如引用[2]所述)。 在代码实现中: - 每个I2C从机模块有自己的控制逻辑。 - 输出合并:SDA总线连接到所有从机的三态输出。 例如,在Verilog中: ```verilog wire sda_bus = 1'b1; // 上拉,初始高 assign sda_bus = (output_enable1) ? data1 : 1'bz; assign sda_bus = (output_enable2) ? data2 : 1'bz; // But multiple assigns to same wire is illegal; instead, use tri-state with multiple drivers. // Correct way: wire sda_bus; assign sda_bus = (output_enable1) ? data1 : 1'bz; assign sda_bus = (output_enable2) ? data2 : 1'bz; // This might cause contention in simulation, but for synthesis, it's fine as long as only one drives at a time. // In practice, for I2C, it's common to have multiple drivers on the same wire. ``` 为了安全,使用一个wire,并允许多个三态驱动。 另一种方法是使用逻辑门合并output_enable,但通常不需要,因为开漏结构自然处理。 回答结构: - 先解释背景。 - 给出合并方法。 - 基于引用提供例子。 - 确保使用中文。 - 添加相关问题。 最后,生成相关问题。 </think>### 多个IIC从机的pad中output_enable合并方法 在I2C(IIC)通信中,多个从机设备共享SDA(Serial Data Line)时,需要正确处理output_enable信号(输出使能信号),以避免总线冲突并确保仲裁机制正常工作。output_enable信号控制三态门的输出状态(驱动数据或高阻态),使设备能够在需要时驱动SDA线或释放总线。合并方法的核心是结合I2C协议的开漏(Open-Drain)特性和三态门控制逻辑,确保多个从机的output_enable信号协同工作。以下是详细解释和实现方法: #### 1. **背景理解** - **I2C总线结构**:SDA线是共享的,多个设备通过开漏输出连接(只能拉低线路或输出高阻态,高电平由上拉电阻提供)。仲裁机制确保只有一个设备在给定时间驱动总线[^2]。 - **output_enable的作用**:每个从机的output_enable信号决定其是否驱动SDA线: - 当output_enable为高时,设备输出数据(仅能驱动低电平,因为开漏结构)。 - 当output_enable为低时,设备输出高阻态(Z),释放总线。 - **合并需求**:多个从机的output_enable信号需要合并为一个逻辑输出,以控制共享SDA线的三态门。这通常在FPGA、ASIC或微控制器中通过硬件描述语言(如Verilog)实现。 #### 2. **合并方法** 合并多个output_enable信号的常规方法是使用“线与”(Wired-AND)逻辑,利用开漏特性简化设计。以下是两种常见实现方式: - **方法1: 基于Verilog的三态总线合并(推荐)** - **原理**:在硬件描述语言中,定义一个共享的三态总线(tri-state bus),每个从机的output_enable和data信号独立连接到该总线。当任一设备的output_enable高时,它驱动数据;否则输出高阻态。仲裁机制确保仅一个设备在仲裁赢家时驱动总线。 - **Verilog示例代码**: ```verilog // 定义共享SDA总线线网(tri类型) wire sda_bus; // 从机1的输出控制 assign sda_bus = (output_enable1) ? data1 : 1'bz; // output_enable1高时输出data1(0或1),否则高阻 // 从机2的输出控制 assign sda_bus = (output_enable2) ? data2 : 1'bz; // 同上 // 可选:添加更多从机 // assign sda_bus = (output_enableN) ? dataN : 1'bz; // 总线连接:sda_bus直接连接到I2C SDA物理引脚 ``` - **说明**: - 这种方法直接利用Verilog的三态门特性。当多个assign驱动同一线网时,综合工具会自动处理为“线与”逻辑(开漏输出)。 - 如果多个设备同时尝试驱动(例如,仲裁丢失),仲裁机制会强制输家切换到高阻态,防止冲突[^2]。 - 优点:简单高效,无需额外逻辑门,适用于FPGA或ASIC设计。 - **方法2: 使用逻辑门合并output_enable信号** - **原理**:对于纯数字逻辑设计,可以使用AND或OR门合并output_enable信号,生成一个全局控制信号。但需注意,I2C的开漏特性要求输出为高阻态时总线由上拉电阻拉高,因此合并逻辑需匹配协议。 - **逻辑设计**: - output_enable信号的合并应为“逻辑AND”:只有当所有设备output_enable低时,全局output_enable才低(总线高阻);否则,任一设备高时,总线可被驱动。 - 但实际中,由于仲裁存在,通常不需要显式合并output_enable;每个设备独立控制其输出,SDA总线自动处理冲突。 - **简化实现**: ```verilog // 计算全局output_enable(可选,但通常直接使用方法1) wire global_output_enable = output_enable1 | output_enable2; // 使用OR门合并 assign sda_bus = (global_output_enable) ? combined_data : 1'bz; // combined_data需从设备数据中解码 ``` - 注意:combined_data需要解码哪个设备在驱动(通过仲裁状态),但仲裁由硬件自动处理,因此方法1更直接。 #### 3. **关键注意事项** - **仲裁处理**:多个设备同时驱动时,I2C硬件检测仲裁丢失(如I2C_I2SR[IAL]位),输家自动切换为从接收模式并释放总线(output_enable变低),无需软件干预[^2]。 - **高阻态的重要性**:未驱动的设备必须输出高阻态(1'bz),避免总线电平冲突。 - **GPIO配置**:确保每个从机的pad配置为GPIO模式,支持三态控制(如引用[3]所述的控制寄存器设置)[^3]。 - **硬件优化**:在物理层,SDA线需添加外部上拉电阻(典型值4.7kΩ),确保高电平状态。 #### 4. **参考示例** 基于引用[1]的三态门控制逻辑,扩展到多个从机: ```verilog // 假设有三个I2C从机 wire sda_bus; // 从机1:output_enable1控制输出 assign sda_bus = (output_enable1) ? data1 : 1'bz; // 从机2:output_enable2控制输出 assign sda_bus = (output_enable2) ? data2 : 1'bz; // 从机3:output_enable3控制输出 assign sda_bus = (output_enable3) ? data3 : 1'bz; // 读取SDA输入(当所有output_enable低时,总线为输入状态) wire sda_input = sda_bus; ``` - 此代码在综合后,会自动处理多个三态驱动。仲裁丢失时,硬件设置状态位,软件可读取I2C_I2SR[IAL]处理错误[^2]。 ### 相关问题 1. I2C仲裁丢失时如何从硬件层面自动恢复? 2. 在Verilog中实现多个三态门驱动的常见错误有哪些?如何避免? 3. GPIO控制寄存器如何配置以支持I2C从机的三态输出模式?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值