Android使用AudioTrack发送红外信号

最近要做一个项目,利用手机的耳机口输出红外信号,从而把手机变成红外遥控器,信号处理的知识基本都还给老师了,刚开始真的挺头疼。找了不少资料研究了一下,总算有点心得,在这里做个备忘。

一、音频信号输出原理

音频耳机口输出信号的原理已经有大牛的文章,参考http://blog.csdn.net/xl19862005/article/details/8522869

再补充一点个人的理解,Android音频输出采样率一般为44.1kHz,AudioTrack源码中限制最大采样率为48kHz,也就是说耳机音频口输出的音频频率应该在20kHz左右,基本就是Android音频输出频率极限了。红外信号载波一般是38kHz,所以单纯的想通过音频信号是达不到要求的,需要借助外部硬件,找了一下,发现某宝上有的卖的,配套的app也有,下来试了一下,效果不错。不过既然是自己开发,需要搞清原理,反编译看了一下,核心代码都是native code,还是走正路,自己研究怎么实现。

网上找了一些相关资料,Linux平台下有相关的开源项目LIRC(Linux Infrared Remote Control):http://www.lirc.org/,支持各种类型的硬件,可以通过配置文件来支持各种类型的遥控设备,电视、dvd等等,是一个相对成熟的项目,目前google play中有很多红外遥控的应用都是基于此项目开发的。不过我这边只关注耳机口输出红外,LIRC中关于audio耳机口输出原理图(http://www.lirc.org/html/audio.html):

                    

利用耳机的左右声道,输出19kHz音频,通过左边的电路图,输出38kHz。

二、实现

原理搞清楚了,接下来实现,通过AudioTrack输出19kHz的正弦波形即可。这里没有将LIRC整体移植到android上,一来工程量太大,二来我只是用耳机这一种,其他的用不上,主要借鉴其中的音频输出原理。LIRC移植到Android可以参考开源项目irdroid:http://www.irdroid.com/

核心代码, 输出19kHz正弦,参考国外大牛:http://stackoverflow.com/questions/2413426/playing-an-arbitrary-tone-with-android

public SignalProcessor(final int frequency) {
    int buffSize = AudioTrack.getMinBufferSize(this.sampleRate,
                AudioFormat.CHANNEL_CONFIGURATION_STEREO,
                AudioFormat.ENCODING_PCM_16BIT) * 4;

    genSignal = new byte[buffSize];
    genSpace = new byte[buffSize];

    for (int j = 0; j < buffSize;) {
        double dVal = Math.sin(2 * Math.PI * ((double)j)/4.0
                        / (((double)sampleRate) / ((double)frequency)));
        final short val = (short) ((dVal * 32767));
        final short val_minus = (short) -val;
        // in 16 bit wav PCM, first byte is the low order byte
        genSpace[j] = 0;
        genSignal[j++] = (byte) (val & 0x00ff);
        genSpace[j] = 0;
        genSignal[j++] = (byte) ((val & 0xff00) >>> 8);
        genSpace[j] = 0;
        genSignal[j++] = (byte) (val_minus & 0x00ff);
        genSpace[j] = 0;
        genSignal[j++] = (byte) ((val_minus & 0xff00) >>> 8);
    }

    audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
                        this.sampleRate, AudioFormat.CHANNEL_CONFIGURATION_STEREO,
                        AudioFormat.ENCODING_PCM_16BIT, buffSize,
                        AudioTrack.MODE_STREAM);
    audioTrack.play();
}

public void play(final ArrayList<Integer> SignalSpaceList) {
        boolean signal = true;
        int count=0;
        for (Integer d : SignalSpaceList) {
                final int stop = (int) (((double) (d * sampleRate)) / 1000000.0) *4 ;
                if (signal)
                        for (int i = 0; i < stop;)
                        {
                                if (stop - i < buffSize)
                                        count= audioTrack.write(genSignal, 0, stop - i);
                                else
                                        count = audioTrack.write(genSignal, 0, buffSize);
                                if(count>0)
                                        i+=count;
                        }
                else
                        for (int i = 0; i < stop;)
                        {
                                if (stop - i < buffSize)
                                        count= audioTrack.write(genSpace, 0, stop - i);
                                else
                                        count = audioTrack.write(genSpace, 0, buffSize);
                                if(count>0)
                                        i+=count;
                        }

                signal = !signal;
        }
}

解释一下:

public void play(final ArrayList<Integer> SignalSpaceList)

传入信号与空闲时间的一个list,比如NEC编码中如图:

HEAD信号时间9ms,空闲时间4.5ms,list中传入9000,4500

测试耳机口单声道输出波形:

连接外设之后,输出方波:

时间: 2024-08-29 13:31:45

Android使用AudioTrack发送红外信号的相关文章

Android 自定义广播发送和接收

android系统会发送许多系统级别的广播,比如屏幕关闭,电池电量低等广播.同样应用可以发起自定义“由开发者定义的”广播.广播是从一个应用内部向另一个应用发送消息的途径之一. BroadcastReceiver是一个可以监听和响应广播的组件.本文中,我们将会演示如何发送自定义广播以及如何通过编程和使用Manifest文件定义一个BroadcastReceiver来监听这一广播.我们最后只要调用sendBroadcast就可以发送广播信息了. 1,编写MyReceiver,MyReceiver代码

Android浏览器:httpclient发送请求时TCP发送带有多个Segments

Android浏览器在发送HTTP(get/post)请求时,将请求首部切成多个segment.抓包如下: iPhone5没有发现此现象. ...待完善...

Qt on Android: Qt Quick 事件处理之信号与槽

前面两篇文章< Qt on Android:QML 语言基础>和<Qt on Android: Qt Quick 简单教程>中我们介绍了 QML 语言的基本语法和 Qt Quick 的常见元素,亲们,通过这两篇文章,您应该已经可以完成简单的 Qt Quick 应用了.接下来呢,哈,我们要介绍 Qt Quick 中一个灰常灰常重要的主题:事件处理.这将是比较长长长长的一篇,哦,不还有后续好几篇--废话少说,还是谈正事儿吧兄弟姐妹们. 本文参加 CSDN 博文大赛,请点这里投我一票,谢

android 向服务器Get和Post请求的两种方式,android向服务器发送文件,自己组装协议和借助第三方开源

/** * @author [email protected] * @time 20140606 */ package com.intbird.utils; import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream

处理android 经典蓝牙发送文件时接收包的问题

需求:android 经典蓝牙发送文件,发送端支持暂停操作(变态!!!!),还想要断点续传(更变态!!!) 大致实现:   client端发送定长包,文件首包包头(固定长度)包含此文件标示(名称,文件流总长度等),并且要处理好socket缓存区 溢出的问题,防止出现丢包. server端从socket读取数据时按照定长包读取,长度不够等下组数据来,长度长了截掉,每个数据流进行包头判断,前一文件未收完的情况下,收到包头数据流,就丢弃,开始接受新的文件流. case点:包头判断的过程:有两种方式:

Android(NotificationManager 发送通知)

该应用的界面如下,界面代码在此不再给出 MainActivity.java 1 public class MainActivity extends Activity { 2 private TextView tvTitle; 3 private TextView tvContent; 4 private Button btnSend; 5 private String title; 6 private String content; 7 8 public void onCreate(Bundle

Android应用程序发送广播(sendBroadcast)的过程分析

文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6744448 前面我们分析了Android应用程序注册广播接收器的过程,这个过程只完成了万里长征的第一步,接下来它还要等待 ActivityManagerService将广播分发过来.ActivityManagerService是如何得到广播并把它分发出去的呢?这就是 本文要介绍的广播发送过程了. 广播的发送过程比广播接收器的注册过程要复杂得多了

Android Wear 用于发送与同步数据的数据类型与接口概述

Android Wear数据层的API,是google play service的一部分,为您的手持设备和可穿戴式应用程序的通信通道. Api包括一系列数据对象,可以让系统通过监听器和线路通知app数据层重要的事件. 以下是几种对象类型. Data Item 提供数据存储用于手机和wear的自动同步. Messages 消息API可以实现fire-and-forget模式,如在wear中控制手机播放器控制或者通过手机发送一个意图给wear,当建立连接或者发生传输错误的时候,都会提供消息.消息是一

Android 使用 RemoteViews 发送自定义通知 ,遇到 Couldn&#39;t expand RemoteViews问题总结

在RemoteViews这种调用方式中,你只能使用以下几种界面组件: Layout:     FrameLayout, LinearLayout, RelativeLayout Component:   AnalogClock, Button, Chronometer, ImageButton, ImageView, ProgressBar, TextView, ViewFlipper, ListView, GridView, StackView, AdapterViewFlipper SO,当