Voice chat rooms or multi-person voice chat are common functions in instant messaging applications. For example, QQ voice discussion groups are widely used.
This article will implement a simple voice chat room, allowing multiple people to access the same room for voice communication. First look at the running effect:
The three diagrams from left to right are the logon interface, the main interface of the voice chat room, and the main interface marked with various controls.
(If you think the interface is too ugly, it doesn't matter. After downloading the source code, you can beautify it yourself ~~)
I. C/S structure
Obviously, my voice chat room uses a C/S structure. The entire project structure is relatively simple, as shown below:
The underlying layer of this project is built based on omcs. In this way, the server basically does not write code, and the omcs server is taken for use directly; the client is more troublesome. Next I will focus on the development of the client.
2. client-side control-based development
The client has developed multiple custom controls and then assembled them to complete the functions of the voice chat room. For ease of explanation, the graph on the main interface is marked to indicate various custom controls.
Now we will introduce the various controls:
1. decibel display
The decibel display is used to display the sound size, such as the size of the sound collected by the microphone or the size of the sound played by the speaker. AboveFigure 3Marked.
(1) Fourier Transformation
Fourier transformation is used to convert the acoustic data to the component Bay intensity. It corresponds to the fouriertransformer static class in the client project. The source code is relatively simple, so we will not post it. Let's check it out.
(2) decibeldisplayer
Decibeldisplayer uses prograssbar to display the sound intensity.
Whenever sound data is handed over to decibeldisplayer for display, decibeldisplayer first calls the Fourier transform above to convert it to decibels, and then maps it To the value corresponding to prograssbar.
2. Speaker control speakerpanel
Speakerpanel is used to represent a member in the chat room.Figure 1. It displays the Member's ID, the member's sound intensity (using the decibeldisplayer control), and its microphone status (enabling and referencing ).
This control is very important. I will post the source code:
Public partial class speakerpanel: usercontrol, idisposable {private chatunit; Public speakerpanel () {initializecomponent (); this. setstyle (controlstyles. resizeredraw, true); // adjust the size of the hour to re-paint this. setstyle (controlstyles. optimizeddoublebuffer, true); // double buffer this. setstyle (controlstyles. allpaintinginwmpaint, true); // do not erase the background. this. setstyle (controlstyles. userpaint, true); // draw this by yourself. updatestyles ();} Public String memberid {get {If (this. chatunit = NULL) {return NULL;} return this. chatunit. memberid ;}} public void initialize (chatunit unit) {This. chatunit = unit; this. skinlabel_name.text = unit. memberid; this. chatunit. microphoneconnector. connectended + = new cbgeneric <omcs. passive. connectresult> (microphoneconnector_connectended); this. chatunit. microphoneconnector. owneroutputchanged + = new Cbgeneric (microphoneconnector_owneroutputchanged); this. chatunit. microphoneconnector. audiodatareceived + = new cbgeneric <byte []> (microphoneconnector_audiodatareceived); this. chatunit. microphoneconnector. beginconnect (unit. memberid);} public void initialize (string curuserid) {This. skinlabel_name.text = curuserid; this. skinlabel_name.forecolor = color. red; this. picturebox_mic.visible = false; this. Decibeldisplayer1.visible = false;} void microphoneconnector_audiodatareceived (byte [] data) {This. decibeldisplayer1.displayaudiodata (data);} void microphoneconnector_owneroutputchanged () {If (this. invokerequired) {This. begininvoke (New cbgeneric (this. microphoneconnector_owneroutputchanged);} else {This. showmicstate () ;}} private connectresult; void microphoneconnector_connect Ended (connectresult res) {If (this. invokerequired) {This. begininvoke (New cbgeneric <connectresult> (this. microphoneconnector_connectended), Res);} else {This. connectresult = res; this. showmicstate () ;}} public void dispose () {This. chatunit. close ();} private void showmicstate () {If (this. connectresult! = Omcs. passive. connectresult. succeed) {This. picturebox_mic.backgroundimage = This. imagelist1.images [2]; this. tooltip1.settooltip (this. picturebox_mic, this. connectresult. tostring ();} else {This. decibeldisplayer1.working = false; If (! This. chatunit. microphoneconnector. owneroutput) {This. picturebox_mic.backgroundimage = This. imagelist1.images [1]; this. tooltip1.settooltip (this. picturebox_mic, "microphone disabled by friends"); return;} If (this. chatunit. microphoneconnector. mute) {This. picturebox_mic.backgroundimage = This. imagelist1.images [1]; this. tooltip1.settooltip (this. picturebox_mic, "mute");} else {This. picturebox_mic.backgroundimage = This. im Agelist1.images [0]; this. tooltip1.settooltip (this. picturebox_mic, "normal"); this. decibeldisplayer1.working = true ;}} private void picturebox_mic_click (Object sender, eventargs e) {If (! This. chatunit. microphoneconnector. owneroutput) {return;} This. chatunit. microphoneconnector. Mute =! This. chatunit. microphoneconnector. Mute; this. showmicstate ();}}
(1) In the code, chatunit represents the members in the current chat room. We use its microphoneconnector to connect to the target Member's microphone.
(2) subscribe to the audiodatareceived event of microphoneconnector. When receiving voice data, hand it over to decibeldisplayer to display the sound size.
(3) subscribe the connectended and owneroutputchanged events of the microphoneconnector, and display the status of the microphone icon in the speakerpanel space based on the results (corresponding to the showmicstate method ).
3. multiaudiochatcontainer Control
Corresponding to multiaudiochatcontainerFigure 2Annotation control, which mainly performs the following tasks:
(1) join a chat room during initialization: Call the join method of the chatgroupentrance attribute of imultimediamanager.
(2) Use flowlayoutpanel to list the speakerpanel corresponding to each member in the chat room.
(3) When a member joins or exits the chat room (corresponding to the someonejoin and someoneexit events of the chatgroup), the corresponding speakerpanel instance is dynamically added or removed.
(4) Expose control of your device (microphone and Speaker) through the checkbox. We can enable or disable our own microphones or speakers.
(5) Note that the close method is provided, which means that when the host form containing the control is closed, you need to call its close method to release resources such as microphone connectors held inside it.
After completing multiaudiochatcontainer, the core of our chat room is almost the same. The next step is to get a main form, drag the multiaudiochatcontainer, initialize imultimediamanager, and pass it to the multiaudiochatcontainer.
3. Download source code
The above only focuses on implementing multi-person voice chat rooms, and is not comprehensive. You can download the following source code for more in-depth research.
Audiochatroom.rar
Finally, let's talk about the deployment steps:
(1) Deploy the server on one machine and start the server.
(2) modify the serverip in the client configuration file to the IP address of the server just now.
(3) run the client on multiple machines and log on to the same room (for example, the default r1000) with different accounts ).
(4) so many users are in the same chat room for voice chat.
Implement a simple voice chat room (source code)