文旨在介紹一下用Qt來實現局域網音頻通話功能
QAudioInput、QAudioOutput(Qt采集和播放音頻類)
QUdpSocket(Qt的UDP通信類)
??話不多說,直接上代碼鏈接,想下載的朋友可以直接去gitee下載。
??整體的思路就是,讀取聲卡的數據,通過UDP發送出去,同時也會讀取UDP發送過來的流的數據,寫入到音頻播放設備里進行播放。
以下是一些比較簡單的對這兩個技術點的解釋,以及部分代碼實現細節。
QAudioFormat(音頻采樣格式)
這個類,保存了音頻流的參數信息。主要的參數有:
采樣頻率代表,在一秒鐘里面,采樣的音頻的數量。采樣頻率越大,就代表這個聲音的振幅越準確,換言之就是聲音的質量也就越高。
采樣位數代表,對采樣的聲音的振幅等級數量。采樣位數越大,聲音振幅的劃分越細,得到的聲音的就越真實,噪聲就越少。
這個類是用來保存音頻播放設備的一些信息的,在這里,我們主要用來獲取設備所支持的語音格式。
這兩個類,是Qt中的用于采集和播放音頻的類。簡單的用法如下:
// 設置音頻采樣的參數
m_format.setSampleRate(8000);
m_format.setChannelCount(1);
m_format.setSampleSize(8);
m_format.setCodec("audio/pcm");
m_format.setByteOrder(QAudioFormat::LittleEndian);
m_format.setSampleType(QAudioFormat::SignedInt);
QAudioDeviceInfo info=QAudioDeviceInfo::defaultInputDevice();
if (!info.isFormatSupported(m_format)) {
qWarning() << "Default format not supported, trying to use the nearest.";
m_format=info.nearestFormat(m_format);
}
// 用采樣的參數來實例化一個QAudioInput對象
m_audioInput=new QAudioInput(m_format);
// 用采樣的參數來實例化一個QAudioOutput對象
m_audioOutput=new QAudioOutput(m_format, this);
m_outputDevice=m_audioOutput->start();
【領QT開發教程學習資料,點擊下方鏈接莬費領取↓↓,先碼住不迷路~】
點擊→領取「鏈接」
這兩個類有一個函數start( ),這個函數會開啟音頻的讀取或者寫入,并返回一個對應的QIODevice,用來從設備里讀取和寫入音頻數據。
當通話接通的時候,打開QAudioInput,將音頻流數據,通過UDP發送到對方端口。
void MainWindow::slot_callResponse(int response)
{
ui->stackedWidget->setCurrentIndex(0);
m_dialogTimer.stop();
if (response==0) {
slot_connected();
m_inputDevice=m_audioInput->start();
connect(m_inputDevice, &QIODevice::readyRead, this, &MainWindow::slot_sendAudioData, Qt::UniqueConnection);
} else if (response==1) {
// TODO 添加拒絕通話時,將等待框關掉
}
}
void MainWindow::slot_sendAudioData()
{
m_socket.writeDatagram(m_inputDevice->read(1024), QHostAddress(m_targetIP), m_targetPort);
}
這個類是Qt的udp通信的類,詳細的類的介紹,可以看Qt的幫助文檔。在這個項目,主要用到了幾個函數:
bind
??這個函數用來綁定到某個ip和端口上,代表發到這個ip和這個端口上的數據,能被當前socket認為是發給自己的。當然,如果你僅僅只要發送udp數據的話,是不需要進行bind的。
readyRead
??這是一個信號,當數據準備好可以讀取的時候,就會發射這個信號。這個時候,就可以調用reciveDatagram來讀取數據。
使用代碼如下:
void RecvData::slot_start()
{
qDebug() << QThread::currentThread();
QString dir=QApplication::applicationDirPath();
QSettings settings(dir+"/config.ini", QSettings::IniFormat);
int port=settings.value("Network/hostPort").toInt();
QString ip=settings.value("Network/hostIP").toString();
m_socket=new QUdpSocket;
int ret=m_socket->bind(QHostAddress(ip), port);
qDebug() << ip << port;
if (!ret) {
QString error=QString("%1:%2 綁定失敗, 原因: %3")
.arg(ip)
.arg(port)
.arg(m_socket->errorString());
Q_EMIT signal_bindFailed(error);
}
connect(m_socket, &QUdpSocket::readyRead, this, &RecvData::slot_writeDataToOutput);
}
在收到UDP的數據時,會對數據進行解析,然后通過信號和槽的方式來執行對應的步驟:
int RecvData::analysisData(const QByteArray &data)
{
if (data.size() > 30)
return 0;
if (data==m_protocolManager.protocolContent(Protocol::CallRequest)) {
m_connectStatus=ConnectStatus::Connected;
Q_EMIT signal_callRequest();
}
if (data==m_protocolManager.protocolContent(Protocol::Accept)) {
m_connectStatus=ConnectStatus::Connected;
Q_EMIT signal_callResponse(0);
}
if (data==m_protocolManager.protocolContent(Protocol::Refuse)) {
m_connectStatus=ConnectStatus::Disconnected;
Q_EMIT signal_callResponse(1);
}
if (data==m_protocolManager.protocolContent(Protocol::HangUp)) {
m_connectStatus=ConnectStatus::Disconnected;
Q_EMIT signal_hangUp();
}
if (data==m_protocolManager.protocolContent(Protocol::Cancel)) {
m_connectStatus=ConnectStatus::Disconnected;
Q_EMIT signal_callCancel();
}
return 1;
}
如果是音頻的數據,就直接將數據寫入到QAudioOutput開啟時返回的QIODevice里,
經常玩英雄聯盟的玩家應該都有一個感覺,就是現在英雄聯盟客戶端啟動真的是越來越慢了,經常要對著那個進入頁面好幾十秒,有時候真的是等得不耐煩了,偶爾想玩一盤游戲,但是等得都沒熱情了,當然英雄聯盟客戶端啟動速度變慢和游戲內新增的許多功能有關,每新增一個功能啟動速度都將更慢一個級別,應該有不少玩家都被游戲剛開始時的英雄聯盟電視臺搞得非常頭疼吧。
然而在英雄聯盟8.14版本中,客戶端的啟動速度將再次變慢,因為今天國服測試服客戶端中是加入了內置語音功能,有點像原來的QT語音,只是現在變成內置的了,游戲內組隊語音(噴人)就更加方便了,但是作為一個一開游戲就喜歡把英雄聯盟后臺程序全部退掉的玩家來說,加入這個功能除了會讓游戲變卡,毫無作用,然而這個功能似乎還不能關閉!簡直坑爹。
拳頭在提升游戲性的同時,我覺得應該更多的考慮到玩家們的體驗才對,現在從進游戲到開局基本上就是十幾分鐘過去了,客戶端還慢的一批,經常開游戲還會出現未知錯誤,也難怪會被這么多玩家吐槽優化越來越差了。
本文由Sir電影原創:dushetv)
這個月,韓劇霸屏。
隔壁表妹對著玄彬和阿澤流口水,肉叔被金宣兒的新劇嚇得一愣一愣。
至于獨具慧眼的Sir嘛。
選擇了這部被遺忘的“神”劇——
《神的測驗:重啟》
?? ?? : ???
說起近幾年的懸疑韓劇,大家的名單上不外乎都是這幾部:《秘密森林》《信號》《特殊失蹤專案組M》《九回時間旅行》《神的禮物-14天》……
但在它們出現之前,懸疑韓劇開山之作卻鮮少被提起。
是時候鄭重介紹這系列了——
自2010年在OCN電視臺播出第一季后,至今播出五季,是目前最長壽的懸疑韓劇系列。
第五季,是時隔四年后的重啟。
主角,是一支“特勤小隊”。
國立科學搜查研究院的韓國大學醫院法醫事務所(下簡稱事務所)。
事務所由海報上的六人組成。
他們不僅有獨立搜查權,而且基本上所有與罕見病相關的案件都會送到這里解決。
簡單說,事務所負責診斷所有案件中的“疑難雜癥”。
每兩集一個案件,每次案件都會涉及一例罕見病。
名字的復雜程度,讓Sir一看到就產生莫名的好奇:
長QT間期綜合征、高同型半胱氨酸血癥、貝赫切特綜合征、克萊恩-萊文綜合癥……
等等。
這么多聽都沒聽過的病,確定不是忽悠?
一開始Sir也這么以為。
實際上,劇里的病例都不是瞎編,基本上全都能在現實中找到對應(除了某些藥物的名字)。
時隔4年回歸的第一集,一上來就是備受爭議的人體自燃。
關于人體自燃,一直屬于“聽過沒見過”的都市傳說。
這四個字自帶恐嚇效果和神秘氣質。
成為許多“添油加醋”的對象。
《狄仁杰之通天帝國》中,就有這么一種殺人手法。
飲下毒液,接觸陽光,平白無故身體就會自燃。
神奇吧?
《神測》選擇這樣的題材作為開篇,意圖再明顯不過——
撕開“神”的面具,測驗出真相。
作為科學劇(而非科幻?。┑摹渡駵y》在最大限度上賦予觀眾正確的科學觀,而并非神化主角。
一來就直接打臉:人體自燃沒有醫學根據。
然后再用案件中的異?,F象發散思維,通過各種細節推導出建立在醫學根據上的結果。
但《神測》能在鮮有系列劇的韓劇里脫穎而出,還拍了五季。
僅僅是因為罕見和獵奇嗎?
太小看它。
在Sir看來,原因有二。
先說第一個,男主角。
在事務所里有這么一位韓振宇(柳德煥 飾)醫生。
不得不說,真是Sir看過的最矮男主角。
1米70都不到的主演,在韓劇一群大長腿演員里毫無優勢。(甚至比劇里女演員都要矮)
劇組合照,讓人心疼的C位
超乎尋常的矮,源于超乎尋常的自信。
矮子柳德煥,以極具反差的表現演活了韓振宇醫生。
他被稱為天才醫生。
可以僅憑尸體上的一個變了色的淋巴結和雨刮上玻璃水換成了酒精的細節,就推斷出自燃產生的原因。
他還毒舌。
別人來跟他打招呼冷漠了點,他就吐槽。
您是被天才騙過錢嗎
這么冷淡
他更愛嘚瑟。
無時無刻不在強調自己知識淵博。
Who am I 我是誰啊
我可是學識淵博的,韓振宇啊
如果直接看第五季,你可能會覺得,這人也太臭屁了吧?
但看下去你就會發現,韓振宇的魅力就在于——
盡管他是天才,卻從不看低別人。
面對同樣是精英的同事,盡管之前吐槽過人家冷淡,但該到同事發揮專長的時候他絕不插嘴,反而甘愿充當配角,在一旁靜靜聆聽。
看他一臉贊賞的小表情。
對于真正努力并出色的人,他會打從心底里認同并不遺余力地維護,甚至把他們當做一家人(因為他沒有家人)。
面對弱者或是罕見病人,他都能設身處地地關懷。
他會怒斥將清潔工人不當回事的醫院管理層。
也會表面吐槽實則不斷地幫助初到乍來的膽小警察。
一而再再而三讓他大聲點說話,失誤了也不斷給他機會嘗試。
他是天才,但也不是神。
別人的痛苦,他也在承受,甚至更深。
韓振宇也是一位罕見病病人。
小時候在不知道的情況下被同學的爸爸當成實驗體,注射了違禁藥刺激大腦。長大后藥物的副作用使他頭部產生劇烈疼痛,無法找到病因,只能用強力鎮痛劑來緩解,過敏反應甚至會令他全身抽搐。
至今,他的病未能找到根治方法,還連名字都沒有。
也因為如此,他比其他人對罕見病更加敏感也更加身同感受。
同為科學家和病人,他也最先能感受關于科學的矛盾。
《神測》長青的第二個理由,由此而生。
作為關注科學最前沿的《神測》,除了為觀眾帶去罕見病的普及,還一直在探討科學的界限。
好比貫穿這一季的,機器與人腦的極限。
第五季一開始就引入了名為“CODAS”的死因判定系統,與時俱進地通過互聯網大數據的方式分析死因進行破案。
比起由人手去解剖,用肉眼發現問題再分析,不僅時間太長,還會有不可控的誤差。
“CODAS”系統,無疑能降低錯誤判斷率。
但技術是冰冷的,盡管能分析出數據和死亡原因,卻無法推導出作案動機和情感理由。
機器與人的較量,暴露了《神測》最后的野心——
科技與人倫的界限。
同類的爭論其實最近大家都聽了不少。
比如,基因編輯。
劇中有一個案例,恰恰對應了現實。
神經科醫生申妍華在進行一項活體試驗。
Sir用四個字簡單概括一下這位醫生做的試驗——
盜夢空間。
解讀大腦的意識并譯碼,記錄夢境并進行視覺重現,通過刺激令患者如同置身于極樂世界,最后帶著對極樂世界的幻想而死亡。
別人是安樂死,它……是“爽死”。
純屬虛構,并非現實已有
申妍華醫生不僅在未經許可的情況下進行活體實驗,還找來罕見病人參與試驗,因為罕見病人某些機能的缺乏,會令實驗效果更顯著。
但參與實驗的人,一個接一個死亡。
她不僅毫不在乎,甚至還加快實驗節奏,找來更多的人。
當韓振宇找上門理論,她卻如此辯解:
她的實驗,是病人希望她這么做的,也是幫助罕見病患者脫離苦海、具有前瞻性的科學實驗。
這套說辭,好像似曾相識?
引發爭議之后,主導基因編輯的科學家賀建奎這樣說:
對于千百萬深受遺傳病或感染病折磨的家庭來說,如果我們擁有這項技術,我們就能幫助他們。
聽起來好像沒毛病。
但科學界擔憂的理由,我們能從《神測》中窺見一二。
劇中申妍華醫生是癌癥末期病人,她是為了自己能以如此方式死去,才找來活人做實驗。
到底是為謀私利,還是為了人類幸福?
韓振宇醫生預見了這一切:
我怕科學的最終領域
會被利用在滿足人類無止境的欲望當中
科技,到底是幫助人類進步的手段,還是人類滿足私欲的工具?
以我們目前的生活來看,顯然是樂觀的,但科學帶來的負面影響,也不容忽視。
回到劇名《神的測驗》。
第一季的開頭就說明——
指代神給予韓振宇醫生作為病人和科學家得面對一個又一個罕見病難題的測驗。
但到了第五季,Sir看到了另一層意思。
這世上,當然沒有神。
神的測驗,就是人的測驗。
是指當科學家在面對未知努力探索時,能否保持對生命的畏懼之心和倫理尺度的良心測驗。
就像那個俯視的鏡頭,至上而下,一覽無遺。
能擁有這樣“上帝視角”的,除了神。
只有你。
本文圖片來自網絡
Sir電影原創,微信ID:dushetv
微信搜索關注:Sir電影
微博搜索關注:毒舌電影