Android 上的点对点音频通话:语音中断和延迟(接收数据包延迟)增加

2024-02-01

我正在尝试在 Android 上建立点对点音频通话。我使用 Android 手机和平板电脑进行通信,但在收到大约 40 个数据包后,手机几乎停止接收数据包,然后突然收到一些数据包并播放它们,依此类推,但等待时间增加。同样,平板电脑最初接收数据包并播放它们,但延迟增加,并且一段时间后语音开始中断,就好像某些数据包丢失一样。知道是什么导致了这个问题......

这是应用程序的代码...我只是在 RecordAudio 类中给出发送者和接收者的 IP 地址,同时在两个设备上运行它。

public class AudioRPActivity extends Activity implements OnClickListener {

    DatagramSocket socketS,socketR;
    DatagramPacket recvP,sendP;
    RecordAudio rt;
    PlayAudio pt;

    Button sr,stop,sp;
    TextView tv,tv1;
    File rf;

    boolean isRecording = false;
    boolean isPlaying = false;

    int frequency = 44100;
    int channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO;
    int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        tv = (TextView)findViewById(R.id.text1);
        tv1 = (TextView)findViewById(R.id.text2);

        sr = (Button)findViewById(R.id.sr);
        sp = (Button)findViewById(R.id.sp);
        stop = (Button)findViewById(R.id.stop);

        sr.setOnClickListener(this);
        sp.setOnClickListener(this);
        stop.setOnClickListener(this);

        stop.setEnabled(false);

        try
        {
        socketS=new DatagramSocket();
        socketR=new DatagramSocket(6000);
        }
        catch(SocketException se)
        {
            tv.setText(se.toString());
            finish();
        }
    }

    public void onClick(View v) {

        if(v == sr)
            record();
        else if(v == sp)
            play();
        else if(v == stop)
            stopPlaying();
    }

    public void play()
    {
        stop.setEnabled(true);
        sp.setEnabled(false);
        pt = new PlayAudio();
        pt.execute();
    }

    public void stopPlaying()
    {
        isRecording=false;
        isPlaying = false;
        stop.setEnabled(false);
    }

    public void record()
    {
        stop.setEnabled(true);
        sr.setEnabled(false);
        rt = new RecordAudio();
        rt.execute();
    }



    private class PlayAudio extends AsyncTask<Void,String,Void>
    {

        @Override
        protected Void doInBackground(Void... arg0)
        {
            isPlaying = true;
            int bufferSize = AudioTrack.getMinBufferSize(frequency, channelConfiguration, audioEncoding);

            byte[] audiodata = new byte[bufferSize];

            try
            {
                AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,frequency,channelConfiguration,
                                                        audioEncoding,4*bufferSize,AudioTrack.MODE_STREAM);
                audioTrack.setPlaybackRate(frequency);
                audioTrack.play();

                while(isPlaying)
                {
                    recvP=new DatagramPacket(audiodata,audiodata.length);
                    socketR.receive(recvP);
                    audioTrack.write(recvP.getData(), 0, recvP.getLength());
                }
                audioTrack.stop();
                audioTrack.release();
            }
            catch(Throwable t)
            {
                Log.e("Audio Track","Playback Failed");
            }
            return null;
        }
        protected void onProgressUpdate(String... progress)
        {
            tv1.setText(progress[0].toString());
        }

        protected void onPostExecute(Void result)
        {
            sr.setEnabled(true);
            sp.setEnabled(true);
        }

    }

    private class RecordAudio extends AsyncTask<Void,String,Void>
    {

        @Override
        protected Void doInBackground(Void... arg0)
        {
            isRecording = true;

            try
            {
                int bufferSize = AudioTrack.getMinBufferSize(frequency, channelConfiguration, audioEncoding);

                AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,frequency,channelConfiguration
                                                            ,audioEncoding,4*bufferSize);   
                byte[] buffer = new byte[bufferSize];
                audioRecord.startRecording();
                int r=0;
                while(isRecording)
                {
                    int brr = audioRecord.read(buffer,0,bufferSize);

                    sendP=new DatagramPacket(buffer,brr,InetAddress.getByName("sender's/receiver's ip"),6000);
                    socketS.send(sendP);
                    publishProgress(String.valueOf(r));

                    r++;
                }

                audioRecord.stop();
                audioRecord.release();

            }
            catch(Throwable t)
            {
                Log.e("AudioRecord","Recording Failed....");
            }


            return null;
        }

        protected void onProgressUpdate(String... progress)
        {
            tv.setText(progress[0].toString());
        }

        protected void onPostExecute(Void result)
        {
            sr.setEnabled(true);
            sp.setEnabled(true);
        }
    }
}

当通过网络发送语音时,如果频率不是 8000,我就会遇到麻烦。 44100听起来很可怕。这可能只适合我的情况。

另一个困难是,对于 UDP,很难说数据包到达的顺序。我已经看到了一个实现,可以将它们恢复到正确的顺序,但我现在找不到它。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android 上的点对点音频通话:语音中断和延迟(接收数据包延迟)增加 的相关文章

  • 当 OnFocusChangeListener 应用于包装的 EditText 时,TextInputLayout 没有动画

    不能比标题说得更清楚了 我有一个由文本输入布局包裹的 EditText 我试图在 EditText 失去焦点时触发一个事件 但是 一旦应用了事件侦听器 TextInputLayout 就不再对文本进行动画处理 它只是位于 editText
  • Java ResultSet 如何检查是否有结果

    结果集 http java sun com j2se 1 4 2 docs api java sql ResultSet html没有 hasNext 方法 我想检查 resultSet 是否有任何值 这是正确的方法吗 if resultS
  • 如何在谷歌地图android上显示多个标记

    我想在谷歌地图android上显示带有多个标记的位置 问题是当我运行我的应用程序时 它只显示一个位置 标记 这是我的代码 public class koordinatTask extends AsyncTask
  • 在我的 Spring Boot 示例中无法打开版本 3 中的 Swagger UI

    我在 Spring Boot 示例中打开 swagger ui 时遇到问题 当我访问 localhost 8080 swagger ui 或 localhost 8080 root api name swagger ui 时出现这种错误 S
  • okhttp 获取失败响应

    我已经在我的 android 客户端中实现了 okhttp 来进行网络调用 当我收到失败响应时 我会收到失败代码以及与该代码相关的文本作为消息 但我没有收到服务器发送给我的自定义失败响应 在我实施的代码中的失败响应中 我收到的消息只是 错误
  • java for windows 中的文件图标叠加

    我正在尝试像 Tortoise SVN 或 Dropbox 一样在文件和文件夹上实现图标叠加 我在网上查了很多资料 但没有找到Java的解决方案 Can anyone help me with this 很抱歉确认您的担忧 但这无法在 Ja
  • Android 2.3 模拟器在更新位置时崩溃

    我正在使用 Eclipse 编写和调试 Android 应用程序 我需要做的事情之一是更新设备的位置 因此我尝试使用模拟器控制窗口中的位置控制面板 在 手动 选项卡上 我选择 十进制 输入有效的纬度和经度 然后单击 发送 不幸的是 接下来发
  • 我应该释放或重置 MediaPlayer 吗?

    我有自己的自定义适配器类 称为 WordAdapter 并且我正在使用媒体播放器 名为pronounce WordAdapter 类中的全局变量 我有不同的活动 其中每个列表项都有线性布局 名为linearLayout 我正在设置onCli
  • 我如何在java中读取二进制数据文件

    因此 我正在为学校做一个项目 我需要读取二进制数据文件并使用它来生成角色的统计数据 例如力量和智慧 它的设置是让前 8 位组成一个统计数据 我想知道执行此操作的实际语法是什么 是不是就像读文本文件一样 这样 File file new Fi
  • 干净构建 Java 命令行

    我正在使用命令行编译使用 eclipse 编写的项目 如下所示 javac file java 然后运行 java file args here 我将如何运行干净的构建或编译 每当我重新编译时 除非删除所有内容 否则更改不会受到影响 cla
  • 上网本上可以进行Android开发吗? [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我想使用我的上网本进行 Android 开发 但是当我尝试使用 Eclipse 运行 SDK 时 没有加载任何内容 上网本对于 Android 开发来
  • 如何使用mockito模拟构建器

    我有一个建造者 class Builder private String name private String address public Builder setName String name this name name retur
  • 通过电子邮件发送文本文件附件

    我正在尝试附加一个文本文件以便通过电子邮件发送 但每当我打开电子邮件应用程序时 它都会说该文件不存在 请帮助 Intent i new Intent Intent ACTION SEND i setType text plain i put
  • 使用反射覆盖最终静态字段是否有限制?

    在我的一些单元测试中 我在最终静态字段上的反射中遇到了奇怪的行为 下面是说明我的问题的示例 我有一个基本的 Singleton 类 其中包含一个 Integer public class BasicHolder private static
  • 没有支持 FEATURE_CAMERA_EXTERNAL 的 Android 设备

    根据this doc https source android com devices camera external usb cameras一些 Android 设备允许使用 Camera2 API 访问外部 USB 摄像头 我检查了大约
  • 如何使用 AccessibilityService 在 Android 中模拟按键

    我正在编写一个辅助服务 我一直在尝试在应用程序上进行一些自动搜索 我使用accessibilityservice action paste来填充EditText 然后我需要模拟软键盘上的按键 但我不知道如何做 你们能帮我一下吗 你可以尝试A
  • 错误:(23, 13) 无法解决:com.google.android.gms:play-services:11.2.0“安装存储库和同步项目”不起作用

    我正在尝试在我的 Android 应用程序中获取位置并更新到服务器 这是我的 Gradle 代码 我在这里包含了compile com google android gms play services 11 2 0 这条线是从文档中 htt
  • 双枢轴快速排序和快速排序有什么区别?

    我以前从未见过双枢轴快速排序 是快速排序的升级版吗 双枢轴快速排序和快速排序有什么区别 我在 Java 文档中找到了这个 排序算法是双枢轴快速排序 作者 弗拉基米尔 雅罗斯拉夫斯基 乔恩 本特利和约书亚 布洛赫 这个算法 在许多数据集上提供
  • Android 屏幕方向错误

    我使用的是 Android HTC HERO 2 1 版本 我写的活动
  • 有没有任何代码可以在android中设置壁纸而无需裁剪和缩放?

    我正在创建一个画廊应用程序 我的第一个应用程序 这是我的代码 Bitmap bmd BitmapFactory decodeStream is try getApplicationContext setWallpaper bmd catch

随机推荐

  • zip 主文件夹,其中包含子文件夹

    我有一个文件夹 里面有一些文件和子文件夹 我将如何读取目录并压缩主文件夹 Ex maindirectory file 1 file 2 subdirectory 1 file 3 file 4 subdirectory 2 file 5 f
  • while循环中的Javascript continue语句导致无限循环

    我正在尝试创建一个while用 continue 语句循环 然而 它似乎导致了无限循环 我不明白为什么 在我看来 下面的代码应该以var tasksToDo然后在 3 处递减至 0 途中跳过数字 2 var tasksToDo 3 whil
  • PDF 文件的正确 MIME 媒体类型

    在处理 PDF 时 我遇到过 MIME 类型application pdf and application x pdf除其他外 这两种类型之间有区别吗 如果有的话 区别是什么 其中一个比另一个更受青睐吗 我正在开发一款网络应用程序 它必须提
  • 如何将dump文件夹导入mongodb数据库?

    我创建了一个mongo dump从远程服务器和 bson and 元数据文件存储到文件夹中 我想要import将此文件夹放入我的本地mongodb 我在用robomongo as a mongodb client ui 我收到一些命令 这些
  • Angular 2:从 ngFor 动态生成的输入中检索数据

    我正在生成一些input text 从数组中使用ngFor 我需要检索用户在其中插入的信息inputs并通过按钮发送到函数 我的代码是下一个 感谢您提前提供的任何帮助 div class container div class well w
  • .NET 中的泛型和鸭子类型 XML?

    我正在使用数据实例的一些 XML 表示形式 我正在使用 NET 序列化来反序列化对象 但我的灵魂中的某些东西因必须编写类来表示 XML 而感到不安 下面是我想做的 但我不知道语法或它是否甚至是可能的 考虑以下 dim xmlObject S
  • PHP crypt() 返回错误答案

    我想我在这里失去了理智 我的网站遇到了一个问题 它随机停止接受登录 我现在已经能够追踪到 crypt 的行为非常奇怪 在我的数据库中 我有用户密码的加密版本 所以假设是 Og12345678 当用户登录时 他们输入密码 我从数据库中读取盐
  • 我应该具备哪些 C# 知识? [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 一个非常开放的问题 我一直在用 C 编程 过去 5 个月我完成的小项目 成功地 今天我去参加了 C 职位的面试 第一个问题 是 告诉我有关拳击的事情
  • 如何在混合容器中选择班级的第一个孩子/最后一个孩子?

    我可以在包含不同类别的子级的 div 中选择某个类别的第一个和最后一个子级吗 例如 div class main div class red div div class red div div class red div div class
  • HTTPS 登录未将 JSESSIONID 保存在 cookie 中 [关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions 我们最近将
  • 如何找出文件的字节顺序?

    如何判断文件是大端还是小端 我只是尝试用 matlab 编写一个大端文件 但可能不起作用 现在我想知道是否可以了解它是什么类型 有什么建议吗 一般来说 无法知道给定的数据文件是使用大端字节格式还是小端字节格式创建的 您需要了解文件的类型 如
  • 从 task.run 传递 Grunt 配置选项

    尝试了一些方法 似乎无法让它发挥作用 但我本以为这很简单 我试图在任务运行时将变量 选项传递到 Grunt 初始化配置中 目前我有两个单独的配置 sass dev options style expanded files expand tr
  • 抽象代数和编程[关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我要开始学习抽象代数 群 环等 我有兴趣了解任何编程语言 如果有的话 可以帮助我学习 尝试我在理论上学到
  • 如何删除 QPixmap 周围的额外边距?

    我画一个QRectF in the paint我的班级的功能并设置QPixmap作为它的刷子 我从包含此的类构建一个对象QRectF 当我将此项目放入场景并设置场景背景时 会出现 QRectF 它也发生在一个QPixmap我添加到场景中 我
  • 如何模拟 JTextField 上的单击?相当于 JButton doClick()?

    我正在开发一个 Java 项目 需要让按键模拟 JTextField 上的单击 我正在寻找相当于 JButton doClick 方法 我试图让按键 enter 执行与单击 JTextField 完全相同的功能 不确定要提供哪些其他信息 提
  • 将焦点设置到 uwp 中的文本框[重复]

    这个问题在这里已经有答案了 我有一个具有 textBox 元素的通用 Windows 平台项目 我想在单击单选按钮时将焦点设置到它 在单选按钮单击事件中 我可以说 txtBoxID IsEnabled true txtBoxID Text
  • 在 Sprite Kit 中显示像素艺术的最佳方式是什么?

    我很好奇如何为我的游戏展示像素艺术 现在我只是调整大小SKScene to be sceneWithSize CGSizeMake 256 192 这是正确的方法还是有更好的方法来完成此类任务 首先 使用场景的默认大小 您不需要缩放或更改它
  • 如何使用 Swift 进行倒计时

    我在制作计时器应用程序时遇到了困难 所以我想现在我解决了它 我可以帮助其他面临问题的人 所以基本上这个应用程序从当前时间倒计时到特定日期 由于堆栈溢出允许采用问答格式 我希望这可以帮助您 请参阅评论以获取解释 使用计时器计算的倒计时和前导零
  • 删除字符串中除字母以外的所有字符

    如果我有一个字符串 ja v a 如何删除所有非字母字符以输出 java 我努力了str str replaceAll W 但无济于事 你能试试这个吗 System out println ja v a replaceAll a zA Z
  • Android 上的点对点音频通话:语音中断和延迟(接收数据包延迟)增加

    我正在尝试在 Android 上建立点对点音频通话 我使用 Android 手机和平板电脑进行通信 但在收到大约 40 个数据包后 手机几乎停止接收数据包 然后突然收到一些数据包并播放它们 依此类推 但等待时间增加 同样 平板电脑最初接收数