【问题标题】:Generate DTMF Tones生成 DTMF 音
【发布时间】:2010-11-26 20:04:23
【问题描述】:

我想知道是否有人遇到过在 iPhone SDK 中生成音调的方法。我正在尝试生成 DTMF 音调,但似乎找不到任何实质性的东西。我还希望能够指定播放音调的时间(即模拟按住按钮而不是简单地按下它..

我发现了一个名为 iPhreak 的开源应用程序。据说它会产生 DTMF 音调来欺骗公用电话(我向你保证这不是我的意图——我的公司处理基于电话的对讲系统)。该应用程序的唯一问题是开源项目中缺少文件。也许其他人过去曾让这个项目工作过?

如果有人知道我会在哪里寻找这样的东西,我会非常感谢我的投票:)

【问题讨论】:

    标签: iphone generator dtmf


    【解决方案1】:

    应该很容易生成自己。 鉴于硬件可以以 44.1 khz 播放 pcm 缓冲区(16 位样本)(它肯定可以使用某些库函数或其他),您只剩下计算波形了:

     const int PLAYBACKFREQ = 44100;
     const float PI2 = 3.14159265359f * 2;
    
     void generateDTMF(short *buffer, int length, float freq1, float freq2)
     {
          int i;
          short *dest = buffer;
          for(i=0; i<length; i++)
          {
               *(dest++) = (sin(i*(PI2*(PLAYBACKFREQ/freq1))) + sin(i (PI2*(PLAYBACKFREQ/freq2)))) * 16383;
          }
     }
    

    16383 已经完成,因为我使用的是加法合成(只需将正弦波加在一起)。因此最大结果是 -2.0 - 2.0 所以乘以 16383 后,我或多或少得到最大 16 位结果:-32768 - +32767

    编辑: 2 个频率是来自维基百科文章的频率,另一个回答的人链接到。两个独特的频率发出 DTMF 声音

    【讨论】:

    • 好吧,也许我在这方面有点落后。你能给我一个你怎么称呼它的例子(例如#3)吗?我了解频率,但并没有真正理解缓冲区的概念。
    • 您创建了一个长度足够长的 16 位有符号数据类型的缓冲区(我不确定在目标 c 中这是如何完成的)。然后选择属于 3 的 dtmf 音调的 2 个频率(697hz 和 1477hz)。使用指向缓冲区的指针调用我的函数,您分配的长度,然后该函数将用 DTMF 音调的波形填充它。然后,您必须将此波形传递给 iPhone 库函数,该函数可以将缓冲区的内容输出到音频硬件。
    • 请注意,缓冲区以 44100 个样本/seq 呈现。因此,在播放波形时,音频硬件应该使用相同的频率,否则 DTMF 频率将关闭。另请注意,如果您希望波形持续 10 秒,则缓冲区长度应为 PLAYBACKFREQ*10。我希望这能解释一下。有关 PCM(波形存储在计算机内存中的方式)的更多信息可以在这里找到:en.wikipedia.org/wiki/Pulse-code_modulation
    • 这确实有道理,尽管我仍然不知道从哪里开始......转到文档。非常感谢。
    • Reinier:我相信 w 是 2pi*f/c 所以公式的一部分不会是 sin(i*(PI2*(freq1/PLAYBACKFREQ))?
    【解决方案2】:

    简单的答案是这样的:

    soundArray = [[NSArray alloc] initWithObjects: 
        [[[SoundEffect alloc] initWithContentsOfFile: @"/System/Library/Audio/UISounds/dtmf-0.caf"] autorelease],
        [[[SoundEffect alloc] initWithContentsOfFile: @"/System/Library/Audio/UISounds/dtmf-1.caf"] autorelease],
        [[[SoundEffect alloc] initWithContentsOfFile: @"/System/Library/Audio/UISounds/dtmf-2.caf"] autorelease],
        [[[SoundEffect alloc] initWithContentsOfFile: @"/System/Library/Audio/UISounds/dtmf-3.caf"] autorelease],
        [[[SoundEffect alloc] initWithContentsOfFile: @"/System/Library/Audio/UISounds/dtmf-4.caf"] autorelease],
        [[[SoundEffect alloc] initWithContentsOfFile: @"/System/Library/Audio/UISounds/dtmf-5.caf"] autorelease],
        [[[SoundEffect alloc] initWithContentsOfFile: @"/System/Library/Audio/UISounds/dtmf-6.caf"] autorelease],
        [[[SoundEffect alloc] initWithContentsOfFile: @"/System/Library/Audio/UISounds/dtmf-7.caf"] autorelease],
        [[[SoundEffect alloc] initWithContentsOfFile: @"/System/Library/Audio/UISounds/dtmf-8.caf"] autorelease],
        [[[SoundEffect alloc] initWithContentsOfFile: @"/System/Library/Audio/UISounds/dtmf-9.caf"] autorelease],
        [[[SoundEffect alloc] initWithContentsOfFile: @"/System/Library/Audio/UISounds/dtmf-0.caf"] autorelease],
        [[[SoundEffect alloc] initWithContentsOfFile: @"/System/Library/Audio/UISounds/dtmf-pound.caf"] autorelease],
        [[[SoundEffect alloc] initWithContentsOfFile: @"/System/Library/Audio/UISounds/dtmf-star.caf"] autorelease],
                  nil];
    

    你有它。标准手机键盘的所有声音,排列整齐,随时供您欣赏。

    【讨论】:

    • 我希望以编程方式生成音调......所以我可以播放它们任意时间。如果我不能让它正常工作,这可能是一个很好的后备。
    • 您可以循环播放这些内容,根据您选择播放它们的方式进行不同的工作量。当然,它们确实是两个纯正弦波,而且很容易创建。但是,您仍然必须以有限的长度创建它们并将它们传递给声音播放器,在这种情况下,一旦声音播放器用完数据,您也必须循环它们。无论哪种方式,您都可能需要做额外的循环工作。
    • 这会让你被 App Store 拒绝吗?
    • 从技术上讲,您没有使用任何禁止或私有的 API。此外,您不必做任何棘手的事情就可以脱离沙盒。我会按原样使用它,如果有问题,请继续将这些文件复制到您的 Bundle 中并与您的应用程序一起分发。如果您被拒绝并不得不将其用作您的计划 B,这不会是一个巨大的打击。
    • 这个例子有内存泄漏。不要发布有明显内存泄漏的代码。
    【解决方案3】:

    Swift DTMF 声音

    我正在尝试生成 PCM 数据,并在 Swift 中提出了这个问题。此函数将生成一个[Float],它们是音频样本。你可以用AVAudio来玩。

    每个DTMF 由一对音调、一个标记长度 (250 ms)、一个空格长度 (250 ms) 组成,当然您还需要指定一个采样频率 (8000 Hz)。 Mark and Space 通常约为 250 毫秒,我称之为标准人工拨号。采样频率很有趣,但需要是最高频率的两倍。为了好玩,你可以把它放到下面来听听会发生什么。

    public static func generateDTMF(frequency1 frequency1: Float, frequency2: Float, markSpace: MarkSpaceType, sampleRate: Float) -> [Float]
    {
        let toneLengthInSamples = 10e-4 * markSpace.0 * sampleRate
        let silenceLengthInSamples = 10e-4 * markSpace.1 * sampleRate
    
        var sound = [Float](count: Int(toneLengthInSamples + silenceLengthInSamples), repeatedValue: 0)
        let twoPI = 2.0 * Float(M_PI)
    
        for i in 0 ..< Int(toneLengthInSamples) {
            // Add first tone at half volume
            let sample1 = 0.5 * sin(Float(i) * twoPI / (sampleRate / frequency1));
    
            // Add second tone at half volume
            let sample2 = 0.5 * sin(Float(i) * twoPI / (sampleRate / frequency2));
    
            sound[i] = sample1 + sample2
        }
    
        return sound
    }
    

    完整的 Playground 可以在 GitHub 下载。

    【讨论】:

      猜你喜欢
      • 2011-04-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-27
      • 1970-01-01
      • 2013-04-23
      • 2013-07-06
      • 1970-01-01
      相关资源
      最近更新 更多