【问题标题】:encode binary to audio python or C将二进制编码为音频 python 或 C
【发布时间】:2013-05-31 13:59:50
【问题描述】:

使用 C 或 python(首选 python),我如何将二进制文件编码为音频,然后通过耳机插孔输出,以及我如何使用麦克风插孔的输入将音频解码回二进制,到目前为止我已经学会了如何使用 python 将文本文件转换为二进制文件,这将类似于 RTTY 通信。

这样我就可以将数据记录到盒式磁带上。

import binascii

a = open('/Users/kyle/Desktop/untitled folder/unix commands.txt', 'r')
f = open('/Users/kyle/Desktop/file_test.txt', 'w')
c = a.read()
b = bin(int(binascii.hexlify(c), 16))
f.write(b)
f.close()

【问题讨论】:

  • 首先,什么是“包含二进制文件的文本文件”。 “文本文件”是包含文本而不是二进制数据的文件;二进制文件是包含二进制数据而不是文本的文件。
  • 二、你想要什么样的编码?您想读取每个字节,将其转换为 0-255 的十进制整数,然后合成说出该数字的声音吗?或者使用每对字节作为 16 位单声道样本以 44.1k 播放?或者将每个字节的低 7 位视为 MIDI 音符编号,以 64 音符/秒播放?还是什么?
  • 感谢您的更正,这令人困惑。
  • 我希望每个位都是表示 1 或 0 的高音或低音

标签: python c audio binary


【解决方案1】:

所以,这里是 Abarnert 的代码,更新到 python3。

import binascii
import pyaudio

a = open('/home/ian/Python-programs/modem/testy_mcTest.txt', 'rb')
c = a.read()
b = bin(int(binascii.hexlify(c), 16))

sample_stream = []
high_note = (b'\xFF'*100 + b'\0'*100) * 50
low_note = (b'\xFF'*50 + b'\0'*50) * 100
for bit in b[2:]:
    if bit == '1':
        sample_stream.extend(high_note)
    else:
        sample_stream.extend(low_note)


sample_buffer = ''.join(map(str, sample_stream))

p = pyaudio.PyAudio()
stream = p.open(format=p.get_format_from_width(1),
                channels=1,
                rate=44100,
                output=True)
stream.write(sample_buffer)

# stop stream (4)
stream.stop_stream()
stream.close()

# close PyAudio (5)
p.terminate()


【讨论】:

    【解决方案2】:

    如果您正在寻找可以执行此操作的库,我建议您使用 libquiet。它使用现有的 SDR 库来执行调制,并提供二进制文件,在一端为您提供管道,另一端使用 PortAudio 将声音直接馈送到声卡。它具有用于“无线”低比特率传输的 GMSK 和用于基于电缆的更高比特率的 QAM。

    【讨论】:

      【解决方案3】:

      所以您想使用音频传输数字信息?基本上你想在软件中实现一个MODEM(不管是纯软件,还是叫modem)。

      调制解调器 (MOdulator-DEModulator) 是一种调制模拟载波信号以对数字信息进行编码的设备,同时也对此类载波信号进行解调以对传输的信息进行解码。目标是产生可以轻松传输和解码以再现原始数字数据的信号。调制解调器可用于任何传输模拟信号的方式,从发光二极管到无线电。 [维基百科]

      在您需要通过模拟媒体传输数据的任何地方都有调制解调器,无论是声音、光还是无线电波。您的电视遥控器可能是红外调制解调器。

      以纯软件实现的调制解调器称为软调制解调器。我在野外看到的大多数软调制解调器都使用某种形式的FSK 调制:

      频移键控 (FSK) 是一种频率调制方案,其中数字信息通过载波的离散频率变化来传输。1 最简单的 FSK 是二进制 FSK (BFSK)。 BFSK 使用一对离散频率来传输二进制(0 和 1)信息。2 在这种方案中,“1”称为标记频率,“0”称为空间频率。 FSK 调制载波的时域如右图所示。 [维基百科]

      有一些非常有趣的应用程序可以通过声波在大气中传输数据 - 我猜这是 shopkick 用于 verify user presence 的。

      对于 Python,请查看 GnuRadio 项目。

      C 库,看Steve Underwood 的工作(但请不要用愚蠢的问题联系他)。我使用他的软调制解调器为Asterisk 引导FAX to email gateway(传真传输只不过是用音频编码以通过电话线传输的黑白TIFF 文件)。

      【讨论】:

      • 我想要一些更简单、更便宜的东西,除了盒式录音机之外不需要新硬件。
      • @kylek:您可以使用纯软件来执行此操作,例如,使用您的笔记本电脑或智能手机对信号进行编码/解码。也就是说,信号处理并不是 CS 中最简单的主题。
      • @kylek:我很确定 Paulo Scardine 的建议是您可以完全用软件构建调制解调器。例如,第一个流行的家用计算机调制解调器只是 BFSK,每秒 300 次更改。那时,您需要特殊的硬件来保持足够快的速度以跟上速度 - 但现在,只需使用与我的答案中的示例非常接近的代码,您就可以使用仅 1% CPU 的高级语言(如 Python)来完成。
      • @kylek:相信我,您不想重新发明轮子,只需使用 BFSK。你可以从 gnuradio 借用一些 Python 代码。
      • @kylek:查看gnuradio.org/redmine/projects/gnuradio/wiki - 你想要的所有内容都在那里,包括 FSK 调制和读/写 WAV 文件。
      【解决方案4】:

      从您的 cmets 中,您希望逐位处理二进制数据,将每个位变成高音或低音。

      您仍然需要准确确定这些高音和低音是什么,以及每个声音的时长(以及两者之间是否有间隔,等等)。如果你让它变慢,比如每个声音 1/4 秒,那么你就是把它们当作音符。如果你让它非常快,比如 1/44100 秒,你就把它们当作样本。人耳在一秒钟内听不到 44100 种不同的声音;相反,它会听到高达 22050Hz 的单一声音。

      一旦你做出了这些决定,你的问题就有两个部分。

      首先,您必须生成一个样本流,例如,每秒包含 44100 个 16 位整数的流。对于非常简单的事情,比如以 44k 16 位单声道格式播放一段原始 PCM 文件,或者生成方波,这是微不足道的。对于更复杂的情况,例如播放一段 MP3 文件或从正弦波和滤波器合成声音,您将需要一些帮助。 audioop 模块和 stdlib 中的其他一些模块可以为您提供基础知识;除此之外,您还需要在 PyPI 中搜索合适的模块。

      其次,您必须将该样本流发送到耳机插孔。 Python 中没有对此的内置支持。在某些平台上,您只需打开一个特殊文件并写入即可。但是,更一般地说,您需要在 PyPI 上找到第三方库。

      更简单的模块适用于一种特定类型的音频系统。 Mac 和 Windows 各有自己的标准,而 Linux 有六种不同的标准。还有一些 Python 模块与更高级别的包装器通信;您可能需要安装和设置包装器,但是一旦您这样做了,您的代码就可以在任何系统上运行。


      那么,让我们通过一个非常简单的例子来研究。假设您已经在系统上设置了 PortAudio,并且您已经安装了 PyAudio 来与它对话。此代码将播放 441Hz 和 220.5Hz(略高于中 C 和低 C)的方波,持续时间不到 1/4 秒(因为这真的很容易)。

      import binascii
      
      a = open('/Users/kyle/Desktop/untitled folder/unix commands.txt', 'r')
      c = a.read()
      b = bin(int(binascii.hexlify(c), 16))
      
      sample_stream = []
      high_note = (b'\xFF'*100 + b'\0'*100) * 50
      low_note = (b'\xFF'*50 + b'\0'*50) * 100
      for bit in b[2:]:
          if bit == '1':
              sample_stream.extend(high_note)
          else:
              sample_stream.extend(low_note)
      
      sample_buffer = b''.join(sample_stream)
      
      p = pyaudio.PyAudio()
      stream = p.open(format=p.get_format_from_width(8),
                      channels=1,
                      rate=44100,
                      output=True)
      stream.write(sample_buffer)
      

      【讨论】:

      • 这是一些有用的建议,我彻底调查了 audioop 模块。
      • 嗨,我想我现在有一个非常相似的任务。在第一个实例中,我也有一个如上所述的数据模式,这意味着一个相当大的数据流看起来像“b'x\xdam\xdd]\xc4\xeemZ\xc7q)2\xcc\xd6' (...)”并在 python 中作为二进制对象给出。我所知道的是它应该代表一种 flac 音频格式。你能告诉我我在这里看到了什么吗?它是我必须转换为 FLAC 的二进制代码吗?
      猜你喜欢
      • 2012-05-14
      • 1970-01-01
      • 2020-05-14
      • 2011-03-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-06
      • 2017-02-04
      相关资源
      最近更新 更多