会员登录 立即注册

搜索

在钢琴曲mp3文件中添加10hz的双耳节拍

[复制链接]
崎山小鹿 发表于 2 小时前 | 显示全部楼层 |阅读模式
崎山小鹿
2 小时前 6 0 看全部
在钢琴曲mp3文件中添加10hz的双耳节拍

钢琴 MP3
   │
   ├── 左声道钢琴 ──┐
   │                ├── + 200 Hz
   │                │
   └── 右声道钢琴 ──┤
                    └── + 210 Hz
                         ↓
                 最终立体声音乐

这样左右耳仍然分别包含:

左耳:钢琴 + 200 Hz
右耳:钢琴 + 210 Hz

两者的频率差为:

210 - 200 = 10 Hz

Python 程序。它可以直接读取 piano.mp3,添加 10 Hz 双耳节拍,再输出 piano_binaural_10hz.wav。

import subprocess
import numpy as np
import soundfile as sf
import os
import tempfile


# ============================================================
# 1. 基本参数
# ============================================================

# ------------------------------------------------------------
# 输入的钢琴 MP3 文件
# ------------------------------------------------------------

input_mp3 = "piano.mp3"


# ------------------------------------------------------------
# 输出文件
# ------------------------------------------------------------

# 第一版建议输出 WAV。
#
# 原因:
# WAV 是无损格式,更适合后续进行 EEG 实验和音频分析。
output_wav = "piano_binaural_10hz.wav"


# ============================================================
# 2. 双耳节拍参数
# ============================================================

# 左耳载频
#
# 左耳最终会增加一个 200 Hz 的正弦波。
left_freq = 200


# 右耳载频
#
# 右耳最终会增加一个 210 Hz 的正弦波。
right_freq = 210


# 计算双耳节拍频率
#
# 210 - 200 = 10 Hz
beat_frequency = abs(
    right_freq - left_freq
)


# ------------------------------------------------------------
# 双耳节拍的音量
# ------------------------------------------------------------
#
# 这是非常重要的参数。
#
# 正弦波本身的范围是:
#
#     -1 ~ +1
#
# 如果直接:
#
#     music + sine_wave
#
# 那么双耳纯音可能非常明显,而且容易造成削波。
#
# 所以这里给它一个比较小的增益。
#
# 例如:
#
#     0.01 = 1%
#     0.02 = 2%
#     0.03 = 3%
#     0.05 = 5%
#
# 第一版建议从 0.02 或 0.03 开始测试。
binaural_volume = 0.03


# ============================================================
# 3. 音量淡入/淡出
# ============================================================
#
# 如果双耳纯音从 0 秒突然出现,可能会产生明显的“啪”的瞬态。
#
# 所以我们让双耳纯音:
#
#     0 秒 → 逐渐增加
#     最后几秒 → 逐渐降低
#
# 单位:秒

fade_in_seconds = 3.0
fade_out_seconds = 3.0


# ============================================================
# 4. 使用 FFmpeg 将 MP3 转成 WAV
# ============================================================

# NumPy 和 soundfile 对 MP3 的支持不如 WAV 直接。
#
# 所以这里使用:
#
#     MP3
#      ↓
#    FFmpeg
#      ↓
#     WAV
#      ↓
#    NumPy
#
# 最后再进行处理。


# 创建临时 WAV 文件

temp_dir = tempfile.gettempdir()

temp_wav = os.path.join(
    temp_dir,
    "piano_binaural_temp.wav"
)


# ------------------------------------------------------------
# FFmpeg 命令
# ------------------------------------------------------------
#
# -y
#     如果文件存在,直接覆盖
#
# -i
#     输入文件
#
# -ar 44100
#     音频采样率 44100 Hz
#
# -ac 2
#     保持双声道
#
# -sample_fmt s16
#     使用 16 bit PCM
#
# 最后是输出 WAV 文件。

ffmpeg_command = [
    "ffmpeg",

    "-y",

    "-i",
    input_mp3,

    "-ar",
    "44100",

    "-ac",
    "2",

    "-sample_fmt",
    "s16",

    temp_wav
]


print("====================================")
print("开始解码 MP3")
print("====================================")


result = subprocess.run(
    ffmpeg_command,
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE,
    text=True
)


# ------------------------------------------------------------
# 检查 FFmpeg 是否执行成功
# ------------------------------------------------------------

if result.returncode != 0:

    print("FFmpeg 执行失败:")
    print(result.stderr)

    raise RuntimeError(
        "MP3 转 WAV 失败,请检查 FFmpeg 是否正确安装。"
    )


print("MP3 解码完成")
print()


# ============================================================
# 5. 读取 WAV
# ============================================================

audio, sample_rate = sf.read(
    temp_wav
)


print("====================================")
print("音频信息")
print("====================================")

print(
    "采样率:",
    sample_rate,
    "Hz"
)

print(
    "音频形状:",
    audio.shape
)


# ============================================================
# 6. 确保音频是立体声
# ============================================================

# 我们必须保证:
#
#     audio[:, 0] → 左声道
#     audio[:, 1] → 右声道
#
# 因为双耳节拍要求:
#
#     左耳 ≠ 右耳
#
# 如果原来的钢琴 MP3 是单声道,
# 我们需要把它复制成两个声道。

if audio.ndim == 1:

    print("原始 MP3 是单声道")
    print("正在复制为立体声")

    audio = np.column_stack(
        (
            audio,
            audio
        )
    )


# 如果不是两个声道,直接报错。

if audio.shape[1] != 2:

    raise ValueError(
        "输入音频必须是单声道或双声道。"
    )


# ============================================================
# 7. 获取音频长度
# ============================================================

total_samples = len(audio)

duration = (
    total_samples
    / sample_rate
)


print(
    f"音频长度: {duration:.2f} 秒"
)

print(
    f"总采样点: {total_samples}"
)


# ============================================================
# 8. 创建时间轴
# ============================================================

# 假设:
#
#     sample_rate = 44100
#
# 那么:
#
# 第一个采样点:
#
#     0 / 44100
#
# 第二个:
#
#     1 / 44100
#
# 第三个:
#
#     2 / 44100
#
# ...
#
# 最终得到以“秒”为单位的时间轴。

t = (
    np.arange(total_samples)
    / sample_rate
)


# ============================================================
# 9. 生成左耳 200 Hz 正弦波
# ============================================================

# 正弦波公式:
#
#     sin(2πft)
#
# 其中:
#
#     f = 200 Hz
#     t = 时间
#
# 所以:
#
#     left_binaural =
#         sin(2π × 200 × t)

left_binaural = np.sin(
    2
    * np.pi
    * left_freq
    * t
)


# ============================================================
# 10. 生成右耳 210 Hz 正弦波
# ============================================================

# 同理:
#
#     right_binaural =
#         sin(2π × 210 × t)

right_binaural = np.sin(
    2
    * np.pi
    * right_freq
    * t
)


# ============================================================
# 11. 创建淡入淡出包络
# ============================================================

# 我们不希望 200/210 Hz 在第一帧突然出现。
#
# 因此创建一个 envelope:
#
#     0
#     ↓
#     慢慢增加
#     ↓
#     1
#     ↓
#     保持
#     ↓
#     慢慢降低
#     ↓
#     0


envelope = np.ones(
    total_samples
)


# ------------------------------------------------------------
# 11.1 淡入
# ------------------------------------------------------------

fade_in_samples = int(
    fade_in_seconds
    * sample_rate
)


# 防止淡入时间超过音频长度。

fade_in_samples = min(
    fade_in_samples,
    total_samples
)


if fade_in_samples > 0:

    envelope[
        :fade_in_samples
    ] = np.linspace(
        0,
        1,
        fade_in_samples
    )


# ------------------------------------------------------------
# 11.2 淡出
# ------------------------------------------------------------

fade_out_samples = int(
    fade_out_seconds
    * sample_rate
)


fade_out_samples = min(
    fade_out_samples,
    total_samples
)


if fade_out_samples > 0:

    envelope[
        -fade_out_samples:
    ] = np.linspace(
        1,
        0,
        fade_out_samples
    )


# ============================================================
# 12. 将淡入淡出应用到双耳信号
# ============================================================

left_binaural *= envelope

right_binaural *= envelope


# ============================================================
# 13. 调整双耳节拍音量
# ============================================================

# 例如:
#
#     binaural_volume = 0.03
#
# 表示把正弦波振幅缩小到原来的 3%。

left_binaural *= binaural_volume

right_binaural *= binaural_volume


# ============================================================
# 14. 将双耳信号加入钢琴左声道
# ============================================================

# 原来的钢琴:
#
#     audio[:, 0]
#
# 是左声道。
#
# 我们把:
#
#     200 Hz
#
# 加进去。

audio[:, 0] = (
    audio[:, 0]
    + left_binaural
)


# ============================================================
# 15. 将双耳信号加入钢琴右声道
# ============================================================

# 原来的钢琴:
#
#     audio[:, 1]
#
# 是右声道。
#
# 我们加入:
#
#     210 Hz
#
# 得到最终右声道。

audio[:, 1] = (
    audio[:, 1]
    + right_binaural
)


# ============================================================
# 16. 防止音频削波
# ============================================================

# 正常 WAV 浮点音频一般应该保持在:
#
#     -1.0 ~ +1.0
#
# 但是:
#
#     钢琴 + 双耳纯音
#
# 叠加之后可能超过这个范围。
#
# 例如:
#
#     1.02
#
# 就超过了最大值。
#
# 如果直接保存,可能产生严重失真。
#
# 所以这里进行限制。

audio = np.clip(
    audio,
    -1.0,
    1.0
)


# ============================================================
# 17. 保存最终 WAV
# ============================================================

print()
print("====================================")
print("正在生成最终 WAV")
print("====================================")

sf.write(
    output_wav,
    audio,
    sample_rate
)


print()
print("====================================")
print("生成完成")
print("====================================")

print(
    "输出文件:",
    output_wav
)

print(
    "左耳钢琴 +",
    left_freq,
    "Hz"
)

print(
    "右耳钢琴 +",
    right_freq,
    "Hz"
)

print(
    "双耳节拍:",
    beat_frequency,
    "Hz"
)

print(
    "双耳信号音量:",
    binaural_volume
)


# ============================================================
# 18. 删除临时 WAV
# ============================================================

try:

    os.remove(
        temp_wav
    )

    print(
        "临时文件已删除"
    )

except OSError:

    pass
天不生墨翟,万古如长夜!以墨运商,以商助墨。金双石科技长期招聘科技研发人才!微信:qishanxiaolu   电话:15876572365   公司:深圳市金双石科技有限公司
回复

使用道具 举报

  • 您可能感兴趣
您需要登录后才可以回帖 登录 | 立即注册 |

本版积分规则 返回列表

管理员给TA私信
以墨运商,以商助墨。

查看:6 | 回复:0

  • 分析验证双耳节拍的存在

    验证方法是: 读取 piano_binaural_10hz.wav 截取中间一段,例如 10 秒附近的 2 秒

    阅读:0|2026-08-26
  • 不同的乐器他们的频谱有什么不同2

    使用 FFmpeg 1. 安装 Python 库 pip install numpy soundfile matplotlib 同时电脑需

    阅读:0|2026-08-26
  • USBTreeView

    Windows的设备管理器中可以查看USB设备的信息: 驱动程序供应商:FTDI, 数字签名者:

    阅读:2137|2026-05-23
  • 电子电路仿真网站

    https://velxio.dev/ Arduino、ESP32 和 Raspberry Pi。 直接在您的浏览器中即可使

    阅读:2290|2026-05-19
  • ESP32 板子为什么识别为 CP2102

    你的ESP32开发板被电脑识别为“CP2102”,这并不是一个错误,而是完全正常的现象。这

    阅读:2669|2026-05-09
  • 固件如何加密

    做固件加密,本质上是防止别人读取或复制你的程序。常见做法分为“芯片级保护 + 软件

    阅读:2768|2026-04-06
  • 高端神经反馈脑波检测系统

    高端神经反馈脑波检测系统分为脑波检测、脑波分析、脑波解码三个部分。 前端主程序

    阅读:17|2026-01-06
  • 国内第三方量化平台有哪些有什么特点

    好的,我们来详细了解一下国内主流的第三方量化平台。这些平台极大地降低了个人投资者

    阅读:4779|2025-12-09
  • 为什么脑波要去除伪迹

    1. 伪迹不是大脑信号 EEG设备记录的是头皮上非常微弱的电位变化(微伏级别,μV)。

    阅读:24|2025-12-05
  • 便携可视化语音AI耳机

    项目起源: 初先生的聊天记录: 你那边掌握的技术,有办法做一个有摄像头的,墨者机

    阅读:3181|2025-12-01
金双石科技,软件开发20年,技术行业领先,您的满意,就是我们的目标,认真负责,开拓进取,让成品物超所值
关于我们
公司简介
发展历程
联系我们
本站站务
友情链接
新手指南
内容审核
商家合作
广告合作
商家入驻
新闻合作

手机APP

官方微博

官方微信

联系电话:15876572365 地址:深圳市宝安区西乡街道宝民二路宝民花园 ( 粤ICP备2021100124号-1 ) 邮箱:qishanxiaolu@qq.com
QQ|Powered by Discuz! X3.5 © 2001-2026 Discuz! Team.
快速回复 返回顶部 返回列表