5.23 学习总结

一.项目优化(语音通话)

实现步骤:

1.用户发送通话申请,并处理通话请求,如果同意,为两个用户之间进行连接。

2.获取到电脑的麦克风和扬声器,将获取到的语音信息转换成以字节数组的形式传递。

3.通过流循环的传递和接收字节数组,保持一个持续的语音通话。

4.另开一个线程当做计时器和结束聊天的作用。

实现代码:

1.获取电脑麦克风,将语音信息转换为字节数组,进行传递的方法(因为要保持通话,所以要循环的去发送字节数组,如果要中断聊天可以使用stop方法,来跳出循环;同时为了快速通畅的通讯,用1kb的数组去传递)

public void run() {

        try {
            captrueOutputStream=new BufferedOutputStream(s.getOutputStream());//建立输出流 此处可以加套压缩流用来压缩数据
        }
        catch (IOException ex) {
            return;
        }

        AudioFormat format =new AudioFormat(8000,16,2,true,true);//AudioFormat(float sampleRate, int sampleSizeInBits, int channels, boolean signed, boolean bigEndian)
        DataLine.Info info = new DataLine.Info(TargetDataLine.class,format);

        try {
            line = (TargetDataLine) AudioSystem.getLine(info);
            line.open(format, line.getBufferSize());
        } catch (Exception ex) {
            return;
        }

        byte[] data = new byte[1024];//此处的1024可以情况进行调整,应跟下面的1024应保持一致
        int numBytesRead=0;
        line.start();

        while (thread != null) {
            numBytesRead = line.read(data, 0,1024);//取数据(1024)的大小直接关系到传输的速度,一般越小越快,
            try {
                captrueOutputStream.write(data, 0, numBytesRead);//写入网络流
            }
            catch (Exception ex) {
                break;
            }
        }

        line.stop();
        line.close();
        line = null;

        try {
            captrueOutputStream.flush();
            captrueOutputStream.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

2.获取电脑扬声器,接收传递来的字节数组,再转换为音频,通过扬声器播放。(接收与发送的类似,不过多赘述)

public void run() {

        AudioFormat format =new AudioFormat(8000,16,2,true,true);//AudioFormat(float sampleRate, int sampleSizeInBits, int channels, boolean signed, boolean bigEndian)
        BufferedInputStream playbackInputStream;

        try {
            playbackInputStream=new BufferedInputStream(new AudioInputStream(s.getInputStream(),format,2147483647));//封装成音频输出流,如果网络流是经过压缩的需在此加套解压流
        }
        catch (IOException ex) {
            return;
        }

        DataLine.Info info = new DataLine.Info(SourceDataLine.class,format);

        try {
            line = (SourceDataLine) AudioSystem.getLine(info);
            line.open(format, bufSize);
        } catch (LineUnavailableException ex) {
            return;
        }

        byte[] data = new byte[1024];//此处数组的大小跟实时性关系不大,可根据情况进行调整
        int numBytesRead = 0;
        line.start();

        while (thread != null) {
            try{
                numBytesRead = playbackInputStream.read(data);
                line.write(data, 0,numBytesRead);
            } catch (IOException e) {
                break;
            }
        }

        if (thread != null) {
            line.drain();
        }

        line.stop();
        line.close();
        line = null;
    }

3.开启计时线程,监听语音聊天过程,添加结束聊天的按钮,中断循环。

private void openCallWindow1(Playback playback) {
        Stage callStage = new Stage();
        callStage.setTitle("通话中");

        BorderPane callRoot = new BorderPane();

        // 创建计时器标签
        Label timerLabel = new Label("00:00:00");
        timerLabel.setStyle("-fx-font-size: 24");
        callRoot.setCenter(timerLabel);

        // 创建关闭按钮
        Button closeButton = new Button("结束通话");
        closeButton.setOnAction(e -> {
            callStage.close();
            playback.stop();
        });
        callRoot.setBottom(closeButton);

        // 创建计时器线程
        Thread timerThread = new Thread(() -> {
            int hours = 0, minutes = 0, seconds = 0;
            while (true) {
                try {
                    // 更新计时器标签
                    String time = String.format("%02d:%02d:%02d", hours, minutes, seconds);
                    Platform.runLater(() -> timerLabel.setText(time));
                    Thread.sleep(1000); // 休眠一秒钟
                    seconds++;
                    if (seconds == 60) {
                        seconds = 0;
                        minutes++;
                    }
                    if (minutes == 60) {
                        minutes = 0;
                        hours++;
                    }
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
            }
        });
        timerThread.setDaemon(true); // 设置为守护线程,以确保程序退出时结束计时器线程
        timerThread.start(); // 启动计时器线程

        Scene scene = new Scene(callRoot, 300, 200);
        callStage.setScene(scene);
        callStage.show();
    }

效果展示:

 

 

 

 

二.算法练题

Codeforces Round 946 (Div. 3) D. Ingenuity-2

 

解题思路:

本题是一到模拟题,按照题目的要求来进行模拟即可,首先从题意我们可以得出以下几点:

1.在竖直或者水平方向(即x或者y方向上)的累计,只能是偶数,如果是奇数即输出 NO。

2.当只要两步时,x和y不可能为0,或者x和y不一样。

3.我们可以通过对x和y的值计算来得出H和R的行动,并且如果要保持一致,每一次的行动都应该是以2为单位进行。

#include<bits/stdc++.h>
using namespace std;
#define N 200005
int n, m, t;
int main()
{
	cin >> t;
	while (t--)
	{
		string s, ss;
		int x=0, y=0;
		cin >> n;
		cin >> s;
        //计算x和y值
		for (int i = 0; i < n; i++) {
			if (s[i] == 'N') y += 1;
			if (s[i] == 'S') y -= 1;
			if (s[i] == 'E') x += 1;
			if (s[i] == 'W') x -= 1;
		}
        //假设一开始都是R行动
		for (int i = 0; i < n; i++) {
			ss += 'R';
		}
		if (x % 2 != 0 || y % 2 != 0) {
			cout << "NO" << endl;
			continue;
		}
		else if (x == 0 && y == 0) {
			if (n == 2) {
				cout << "NO" << endl;
				continue;
			}
            //如果要保持不动,一定会出现相反方向的行动
			else {
				if (s[0] == 'N') {
					ss[0] = ss[s.find('S')] = 'H';
				}
				if (s[0] == 'S') {
					ss[0] = ss[s.find('N')] = 'H';
				}
				if (s[0] == 'W') {
					ss[0] = ss[s.find('E')] = 'H';
				}
				if (s[0] == 'E') {
					ss[0] = ss[s.find('W')] = 'H';
				}
			}
		}
		else
		{   //通过x和y值去模拟一种可能
			for (int i = 0; i < n; i++) {
				if (s[i] == 'N' && y>0)
					ss[i] = 'H', y -= 2;
				if (s[i] == 'S' && y<0)
					ss[i] = 'H', y += 2;
				if (s[i] == 'W' && x<0)
					ss[i] = 'H', x += 2;
				if (s[i] == 'E' && x>0)
					ss[i] = 'H', x -= 2;
			}
		}
		cout << ss << endl;
	}
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/632844.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

小林coding笔记

MySQL执行流程 MySQL 的架构共分为两层&#xff1a;Server 层和存储引擎层。Server 层负责建立连接、分析和执行 SQL。存储引擎层负责数据的存储和提取。 Mysql执行 启动Mysql net start mysql登陆 mysql -u root -p输入密码

C++之单链表与双链表逆序实例(二百七十九)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

17款奔驰GLS450升级头等舱行政独立四座马鞍是什么样体验

五座版本&#xff1a;迈巴赫GLS480的五座版本通常指的是具有五个座位的配置&#xff0c;包括两个前排座椅和三个后排座椅。这种配置适合搭载更多乘客&#xff0c;后排座椅通常为三人座设计&#xff0c;乘坐人数较多。 四座版本&#xff1a;迈巴赫GLS480的四座版本通常指的是具…

正点原子LWIP学习笔记(二)MAC简介

MAC简介 一、MAC简介&#xff08;了解&#xff09;二级目录三级目录 二、ST的ETH框架&#xff08;了解&#xff09;三、SMI站管理接口&#xff08;熟悉&#xff09;四、介质接口MII、RMII&#xff08;熟悉&#xff09; 一、MAC简介&#xff08;了解&#xff09; STM32 的 MAC …

c++笔记3

优先队列 普通的队列是一种先进先出的数据结构&#xff0c;元素在队列尾追加&#xff0c;而从队列头删除。优先队列是一种按照优先级决定出队顺序的数据结构&#xff0c;优先队列中的每个元素被赋予级别&#xff0c;队首元素的优先级最高。 例如&#xff1a;4入队&#xff0c…

Python筑基之旅-MySQL数据库(一)

目录 一、MySQL数据库 1、简介 2、优点 2-1、开源和免费 2-2、高性能 2-3、可扩展性 2-4、易用性 2-5、灵活性 2-6、安全性和稳定性 2-7、丰富的功能 2-8、结合其他工具和服务 2-9、良好的兼容性和移植性 3、缺点 3-1、对大数据的支持有限 3-2、缺乏全文…

Windows系统安装OpenSSH使用VScode远程连接内网Linux服务器开发

文章目录 &#x1f4a1;推荐 前言1、安装OpenSSH2、VS Code配置ssh3. 局域网测试连接远程服务器4. 公网远程连接4.1 ubuntu安装cpolar内网穿透4.2 创建隧道映射4.3 测试公网远程连接 5. 配置固定TCP端口地址5.1 保留一个固定TCP端口地址5.2 配置固定TCP端口地址5.3 测试固定公网…

threejs的基本属性

1.创建场景,摄像机,渲染器,几何体,材质,网格 网格 物体材质 场景.add(网格),网格加入场景中 场景.add(坐标辅助器) 渲染 场景摄像机 相机的轨道控制器是个单独的对象 import ./style.css import * as THREE from three import { OrbitControls } from three/examples/j…

【重学C++】02 脱离指针陷阱:深入浅出 C++ 智能指针

前言 大家好&#xff0c;今天是【重学C】系列的第二讲&#xff0c;我们来聊聊C的智能指针。 为什么需要智能指针 在上一讲《01 C如何进行内存资源管理》中&#xff0c;提到了对于堆上的内存资源&#xff0c;需要我们手动分配和释放。管理这些资源是个技术活&#xff0c;一不…

新媒体运营十大能力,让品牌闻达天下!

" 现在新媒体蓬勃发展&#xff0c;很多品牌都有新媒体运营这个岗位。新媒体运营好的话&#xff0c;可以提高公司品牌曝光、影响力。那新媒体运营具备什么能力&#xff0c;才能让品牌知名度如虎添翼呢&#xff1f;" 信息收集能力 在移动互联网时代&#xff0c;信息的…

你应该用USB还是或耳机插孔连接你的电脑耳机?这里有详细解释

​如果你有一套有线耳机&#xff0c;可以通过USB连接或传统耳机插孔连接到电脑&#xff0c;你可能想知道使用这两个端口选项的实际区别。 使用耳机插孔 如果你使用传统的模拟电缆将耳机连接到计算机&#xff08;或任何带耳机插孔的设备&#xff09;&#xff0c;则耳机的作用与…

英码科技算能系列边缘计算盒子再添新成员!搭载TPU处理器BM1688CV186AH,功耗更低、接口更丰富

在数据呈现指数级增长的今天&#xff0c;越来越多的领域和细分场景对实时、高效的数据处理和分析的需求日益增长&#xff0c;对智能算力的需求也不断增强。为应对新的市场趋势&#xff0c;英码科技凭借自身的硬件研发优势&#xff0c;携手算能相继推出了基于BM1684的边缘计算盒…

Google Earth Engine(GEE)深度学习入门教程-Python数据读入篇

Python数据读入篇 前置条件&#xff1a; GEE预处理影像导出保存为tfrecord的数据包&#xff0c;并下载到本地tensorflow的深度学习环境 本篇文章的目的主要是把Tfrecord格式的数据加载为tf可使用的数据集格式 设定超参数 首先需要设定导出时的波段名称和数据格式&#xff…

linux 排查java内存溢出(持续更新中)

场景 tone.jar 启动后内存溢出,假设pid 为48044 排查 1.确定java程序的pid(进程id) ps 或 jps 都可以 ps -ef | grep tone jps -l 2.查看堆栈信息 jmap -heap 48044 3.查看对象的实例数量显示前30 jmap -histo:live 48044 | head -n 30 4.查看线程状态 jstack 48044

于ThinkPHP开发的赛事报名小程序

基于ThinkPHP开发的赛事报名微信小程序 功能包括 1、参赛公告 2、会员中心&#xff08;会员注册、登录、成绩查询、资料管理、参赛记录管理&#xff09; 3、个人报名和企业报名 &#xff08;身份证验证防止重复报名&#xff09; 4、培训报名 5、查询是否在库人员&#xff0c;根…

深度学习之Pytorch框架垃圾分类智能识别系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景 随着城市化进程的加快和人们环保意识的提高&#xff0c;垃圾分类已成为城市管理的重要一环。然而&am…

git拉取项目前需要操作哪些?

1.输入 $ ssh-keygen -t rsa -C "秘钥说明" 按enter键 2.出现 ssh/id_rsa&#xff1a;(输入也可以不输入也可以) 然后按enter键 3.出现empty for no passphrase&#xff1a;(输入也可以不输入也可以) 然后按enter键 4.出现same passphrase again: (输入也可以不输入也…

4. C++入门:内联函数、auto关键字、范围for及nullptr

内联函数 概念 以inline修饰的函数叫做内联函数&#xff0c;编译时C编译器会在调用内联函数的地方展开&#xff0c;没有函数调用建立栈帧的开销&#xff0c;内联函数提升程序运行的效率 对比C的宏 C语言不足&#xff1a;宏 #define ADD(x, y) ((x)(y))int main() {int ret…

java中的HashSet类

一、HashSet类 实现了Set接口&#xff0c;无法存储重复元素 特点&#xff1a;元素位置无序、无索引、底层是HashMap 1、构造方法 内部是HashMap的构造方法 2、add方法 (1)元素在底层存储使用到了三种数据结构&#xff1a;hash数组、链表、树 (2)添加流程&#xff08;根据…

arcgis 10.6 工具栏操作error 001143 后台服务器抛出异常

arcgis 10.6 工具栏操作error 001143 后台服务器抛出异常 环境 win10arcgis 10.6 问题 执行定义投影要素转线出现 Error: 001143:后台服务器抛出异常&#xff08;差点重装10.6&#xff09; 如下图所示&#xff1a; 解决方法 通过在菜单工具条上单击地理处理 > 地理处…