Programming Forums
User Name Password Register
 

RSS Feed
FORUM INDEX | TODAY'S POSTS | UNANSWERED THREADS | ADVANCED SEARCH

Reply
 
Thread Tools Display Modes
Old Feb 9th, 2008, 1:32 PM   #11
PhilBon
Hobbyist Programmer
 
PhilBon's Avatar
 
Join Date: Nov 2005
Posts: 171
Rep Power: 3 PhilBon is on a distinguished road
Send a message via AIM to PhilBon Send a message via MSN to PhilBon
Re: Streaming Audio over network

What are the problems?
PhilBon is offline   Reply With Quote
Old Feb 9th, 2008, 1:35 PM   #12
Brent
Highly Adaptive Penguin
 
Brent's Avatar
 
Join Date: May 2005
Location: United States
Posts: 249
Rep Power: 4 Brent is on a distinguished road
Re: Streaming Audio over network

The playback is extremely choppy, it is as if each chunk is playing several times before moving on to the next chunk in the list.
Brent is offline   Reply With Quote
Old Feb 9th, 2008, 2:35 PM   #13
PhilBon
Hobbyist Programmer
 
PhilBon's Avatar
 
Join Date: Nov 2005
Posts: 171
Rep Power: 3 PhilBon is on a distinguished road
Send a message via AIM to PhilBon Send a message via MSN to PhilBon
Re: Streaming Audio over network

Have you thought about making it so it has to have 5 items in the list before it's able to play? or something of that sort and when it plays an item it removes it, once the list is empty it puts it on hold.
PhilBon is offline   Reply With Quote
Old Feb 9th, 2008, 5:38 PM   #14
The Dark
Expert Programmer
 
Join Date: Jun 2005
Posts: 816
Rep Power: 4 The Dark is on a distinguished road
Re: Streaming Audio over network

You need to change your queueing code a bit. consider this code:
DWORD WINAPI FillOutput(LPVOID lpParameter)
{
	char data[1024];
	int addrlen=sizeof(sin);
	
	while(true)
	{
		if(Out < MAX_BUFFERS)
		{
			for(b=0; b<=(MAX_BUFFERS-Out); b++)
			{
				recvfrom(client,data,sizeof(data),0,(struct sockaddr*)&sin,&addrlen);
				strcpy(OutQueue[b].data,data);
				Out++;
			}
		}
	}

	return 0;
}
This will copy the received data to the start of the OutQueue each time round the while loop, even if that data hasn't been played yet. This is probably what is causing some of the chunks to play several times.

What you can do for a queue in a fixed buffer is to have a start index and an end index - both of these can just keep incrementing until they hit the OutQueue size and wrap back to the 0. You only need to play something if the start and end indexes are at different values.
Write your data to the end index and increment, read your data for playing from the start index and increment. You will still need to handle the case when you have too much data (e.g. the end index catches up with the start).
I hope that makes sense - I too afraid to re-read it
The Dark is offline   Reply With Quote
Old Feb 9th, 2008, 8:13 PM   #15
Brent
Highly Adaptive Penguin
 
Brent's Avatar
 
Join Date: May 2005
Location: United States
Posts: 249
Rep Power: 4 Brent is on a distinguished road
Re: Streaming Audio over network

Thanks for the solution Dark, im looking into it now.
Brent is offline   Reply With Quote
Old Feb 9th, 2008, 8:26 PM   #16
Brent
Highly Adaptive Penguin
 
Brent's Avatar
 
Join Date: May 2005
Location: United States
Posts: 249
Rep Power: 4 Brent is on a distinguished road
Re: Streaming Audio over network

Ok so this is what your saying Dark:

I create two variables, lets say StartIndex and EndIndex, and every time I add a buffer to the queue I increment these values. So it might look something like this:


c++ Syntax (Toggle Plain Text)
  1.  
  2. int StartIndex, EndIndex;
  3.  
  4. DWORD WINAPI FillOutput(LPVOID lpParameter)
  5. {
  6. char data[BUFFERSIZE];
  7. int addrlen=sizeof(sin),a;
  8.  
  9. while(threadEnd == false)
  10. {
  11. if(StartIndex <= MAX_BUFFERS && EndIndex <= MAX_BUFFERS)
  12. {
  13. for(a=0; a<=(MAX_BUFFERS-Out); a++)
  14. {
  15. recvfrom(client,data,sizeof(data),0,(struct sockaddr*)&sin,&addrlen);
  16. strcpy(OutQueue[a].data,data);
  17. Out++;
  18. }
  19. StartIndex++;
  20. EndIndex++;
  21. }
  22. }
  23.  
  24. return 0;
  25. }
Brent is offline   Reply With Quote
Old Feb 9th, 2008, 8:35 PM   #17
The Dark
Expert Programmer
 
Join Date: Jun 2005
Posts: 816
Rep Power: 4 The Dark is on a distinguished road
Re: Streaming Audio over network

Not quite. It might be better to call the variables WriteIndex and ReadIndex. When you write into the buffer, increment WriteIndex. When you read from the buffer, increment ReadIndex. When ReadIndex and WriteIndex have the same value, there is nothing in the buffer to read.
You don't need the inner for loop as the outer while loop takes care of everything.

Something like (untested):
c++ Syntax (Toggle Plain Text)
  1. int WriteIndex = 0;
  2. int ReadIndex = 0;
  3.  
  4. DWORD WINAPI FillOutput(LPVOID lpParameter)
  5. {
  6. char data[BUFFERSIZE];
  7. int addrlen=sizeof(sin),a;
  8.  
  9. while(threadEnd == false)
  10. {
  11. if ( (StartIndex + 1) % MAX_BUFFERS != EndIndex)
  12. {
  13. recvfrom(client,data,sizeof(data),0,(struct sockaddr*)&sin,&addrlen);
  14. strcpy(OutQueue[StartIndex].data,data);
  15. StartIndex = (StartIndex + 1) % MAX_BUFFERS;
  16. }
  17. }
  18.  
  19. return 0;
  20. }

The "% MAX_BUFFERS" is to wrap the index back to zero if it goes past the end of the queue buffer.
The Dark is offline   Reply With Quote
Old Feb 9th, 2008, 9:23 PM   #18
Brent
Highly Adaptive Penguin
 
Brent's Avatar
 
Join Date: May 2005
Location: United States
Posts: 249
Rep Power: 4 Brent is on a distinguished road
Re: Streaming Audio over network

Ok, thank you for the clarification.
Brent is offline   Reply With Quote
Old Feb 9th, 2008, 9:30 PM   #19
Brent
Highly Adaptive Penguin
 
Brent's Avatar
 
Join Date: May 2005
Location: United States
Posts: 249
Rep Power: 4 Brent is on a distinguished road
Re: Streaming Audio over network

I have done some re-coding using the suggestions but am still having problems. When I start the application and press the talk button, the program exits. Here is the code:

c++ Syntax (Toggle Plain Text)
  1.  
  2. #include<windows.h>
  3. #include<windowsx.h>
  4. #include<winsock2.h>
  5. #pragma comment(lib,"ws2_32.lib")
  6. #include"resource.h"
  7. #include"audio_class.h"
  8.  
  9. #define BUFFERSIZE 1024
  10. #define MAX_BUFFERS 12
  11.  
  12. #define UPPER_THRESHOLD 6 // Delay threshold
  13. #define LOWER_THRESHOLD 0 // Delay threshold
  14.  
  15. HWND hwnd,Hwnd;
  16.  
  17. char strAddress[15];
  18. bool connected=false,talk=false,threadEnd=false;
  19. int error,client,port,len;
  20.  
  21. Audio sound;
  22.  
  23. const char g_szClassName[] = "myWindowClass";
  24.  
  25. WORD sockversion;
  26. WSADATA wsaData;
  27.  
  28. sockaddr_in sin;
  29. sockaddr_in bindAddr;
  30.  
  31. HMENU hMenu, hSubMenu;
  32.  
  33. BOOL CALLBACK dlgfunc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
  34. BOOL CALLBACK conndlg(HWND Hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
  35.  
  36.  
  37. DWORD WINAPI recv_(LPVOID lpParameterm);
  38. DWORD WINAPI send_(LPVOID lpParameter);
  39.  
  40. DWORD FillIn,FillOut,PlayOut,SendIn;
  41. HANDLE Fill_In,Fill_Out,Play_Out,Send_In;
  42.  
  43. struct waveBuffers
  44. {
  45. char data[BUFFERSIZE];
  46. };
  47.  
  48. waveBuffers InQueue[MAX_BUFFERS];
  49. waveBuffers OutQueue[MAX_BUFFERS];
  50.  
  51. int In,Out;
  52. int WriteIndex = 0;
  53. int ReadIndex = 0;
  54.  
  55. DWORD WINAPI FillInput(LPVOID lpParameter)
  56. {
  57. char data[BUFFERSIZE];
  58. int a;
  59.  
  60. while(threadEnd == false)
  61. {
  62. if ( (ReadIndex + 1) % MAX_BUFFERS != WriteIndex)
  63. {
  64. sound.GetInput(data);
  65. strcpy(InQueue[ReadIndex].data,data);
  66. ReadIndex = (ReadIndex + 1) % MAX_BUFFERS;
  67. }
  68. }
  69. return 0;
  70. }
  71.  
  72.  
  73.  
  74.  
  75.  
  76. DWORD WINAPI FillOutput(LPVOID lpParameter)
  77. {
  78. char data[BUFFERSIZE];
  79. int addrlen=sizeof(sin),a;
  80.  
  81. while(threadEnd == false)
  82. {
  83. if ( (WriteIndex + 1) % MAX_BUFFERS != ReadIndex)
  84. {
  85. recvfrom(client,data,sizeof(data),0,(struct sockaddr*)&sin,&addrlen);
  86. strcpy(OutQueue[WriteIndex].data,data);
  87. WriteIndex = (WriteIndex + 1) % MAX_BUFFERS;
  88. }
  89. }
  90.  
  91. return 0;
  92. }
  93.  
  94. DWORD WINAPI PlayOutput(LPVOID lpParameter)
  95. {
  96. char data[BUFFERSIZE];
  97. int a;
  98.  
  99. while(threadEnd == false)
  100. {
  101. //if number of output buffers is greater than UPPER_THRESHOLD
  102. if((WriteIndex + 1) % MAX_BUFFERS != ReadIndex)
  103. {
  104. sound.Play(OutQueue[a].data);
  105. ZeroMemory(OutQueue[a].data, BUFFERSIZE);
  106. WriteIndex = (WriteIndex - 1);
  107.  
  108. }
  109. }
  110.  
  111. return 0;
  112. }
  113.  
  114. DWORD WINAPI SendInput(LPVOID lpParameter)
  115. {
  116. char data[BUFFERSIZE];
  117. int a;
  118.  
  119. while(threadEnd == false)
  120. {
  121. if((ReadIndex + 1) % MAX_BUFFERS != WriteIndex)
  122. {
  123. sendto(client,InQueue[a].data,sizeof(InQueue[a].data),0,(struct sockaddr*)&sin,sizeof(sin));
  124. ZeroMemory(InQueue[a].data, BUFFERSIZE);
  125. ReadIndex = (ReadIndex - 1);
  126. }
  127. }
  128.  
  129. return 0;
  130. }
  131.  
  132.  
  133. void Message(LPCSTR message)
  134. {
  135. MessageBox(NULL, message, "Sound Error", MB_OK | MB_ICONSTOP);
  136. }
  137.  
  138. int WINAPI WinMain (HINSTANCE h,HINSTANCE p,LPSTR lpstr,int nShow)
  139. {
  140. DialogBox(GetModuleHandle(NULL),MAKEINTRESOURCE(DIALOG2),Hwnd,conndlg);
  141. if(connected==true)
  142. {
  143. DialogBox(GetModuleHandle(NULL),MAKEINTRESOURCE(DIALOG1),hwnd,dlgfunc);
  144. }
  145.  
  146. return 0;
  147. }
  148.  
  149. BOOL CALLBACK conndlg(HWND Hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  150. {
  151. switch(msg)
  152. {
  153. case WM_INITDIALOG:
  154. {
  155. sockversion=WSAStartup(0x202,&wsaData);
  156.  
  157. SetDlgItemText(Hwnd,IDC_IPADDR,"127.0.0.1");
  158. SetDlgItemText(Hwnd,IDC_PORT,"23097");
  159. }
  160. break;
  161. case WM_COMMAND:
  162. {
  163. switch(LOWORD(wParam))
  164. {
  165. case IDOK:
  166. {
  167. client=socket(PF_INET,SOCK_DGRAM,0);
  168. if(client==INVALID_SOCKET)
  169. {
  170. MessageBox(Hwnd,"Error creating socket","Error",NULL);
  171. closesocket(client);
  172. }
  173.  
  174. sin.sin_family=PF_INET;
  175.  
  176. port = GetDlgItemInt(Hwnd,IDC_PORT,NULL,false);
  177. sin.sin_port = htons(port);
  178.  
  179. GetDlgItemText(Hwnd,IDC_IPADDR,strAddress,15);
  180. sin.sin_addr.s_addr = inet_addr(strAddress);
  181.  
  182. if((len=GetWindowTextLength(GetDlgItem(Hwnd,IDC_IPADDR))) > 0 &&
  183. (len=GetWindowTextLength(GetDlgItem(Hwnd,IDC_PORT))) > 0)
  184. {
  185. bindAddr.sin_family=PF_INET;
  186. bindAddr.sin_port=htons(port);
  187. bindAddr.sin_addr.s_addr=INADDR_ANY;
  188.  
  189. error=bind(client,(LPSOCKADDR)&bindAddr,sizeof(bindAddr));
  190. if(error == SOCKET_ERROR)
  191. {
  192. MessageBox(Hwnd,"bind() error","Error",NULL);
  193. }
  194. else
  195. {
  196. connected=true;
  197. EndDialog(Hwnd,9);
  198. return TRUE;
  199. }
  200. }
  201. else
  202. {
  203. MessageBox(Hwnd,"Please enter an IP and port number","Msg",NULL);
  204. }
  205. }
  206. break;
  207. case IDCANCEL:
  208. {
  209. closesocket(client);
  210. WSACleanup();
  211. EndDialog(Hwnd,5);
  212. return NOT;
  213. }
  214. break;
  215. default:
  216. return FALSE;
  217. }
  218. }
  219. break;
  220. case WM_CLOSE:
  221. {
  222. closesocket(client);
  223. WSACleanup();
  224. EndDialog(Hwnd,0);
  225. }
  226. break;
  227. default:
  228. return FALSE;
  229. }
  230. return TRUE;
  231. }
  232.  
  233. BOOL CALLBACK dlgfunc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  234. {
  235. switch(msg)
  236. {
  237. case WM_INITDIALOG:
  238. {
  239. if((error=WSAAsyncSelect(client,hwnd,WM_SOCK,FD_CLOSE))==SOCKET_ERROR)
  240. {
  241. MessageBox(hwnd,"Select() error","Error",NULL);
  242. closesocket(client);
  243. return(false);
  244. }
  245. }
  246. break;
  247. case WM_CLOSE:
  248. {
  249. talk=false;
  250. threadEnd=true;
  251.  
  252.  
  253.  
  254. sound.Stop();
  255.  
  256. closesocket(client);
  257. WSACleanup();
  258. EndDialog(hwnd,0);
  259. }
  260. break;
  261. case WM_COMMAND:
  262. switch(LOWORD(wParam))
  263. {
  264. case ID_FILE_EXIT:
  265. {
  266. int exit=MessageBox(hwnd,"Are you sure you want to quit?","Exit",MB_YESNO|MB_ICONQUESTION);
  267. if(exit==IDYES)
  268. {
  269. talk=false;
  270. threadEnd=true;
  271.  
  272.  
  273.  
  274. sound.Stop();
  275. closesocket(client);
  276. WSACleanup();
  277. PostMessage(hwnd, WM_CLOSE, 0, 0);
  278. }
  279. }
  280. break;
  281. case IDOK:
  282. {
  283. if(talk == false)
  284. {
  285. //int err = sound.StartAudio(1024,1,8000,8,0); //begin audio
  286. int err = sound.Start();
  287. if(err == 1)
  288. {
  289. MessageBox(hwnd,"Unable to Start Audio","Error",NULL);
  290. talk = false;
  291. }
  292. else
  293. {
  294. talk = true;
  295. threadEnd=false;
  296. SendDlgItemMessage(hwnd,IDOK,WM_SETTEXT,0,(LPARAM)"Push to stop");
  297.  
  298.  
  299. DWORD FillIn,FillOut,PlayOut,SendIn;
  300. HANDLE Fill_In,Fill_Out,Play_Out,Send_In;
  301.  
  302. Fill_In = CreateThread(NULL,0,FillInput,0,0,&FillIn);
  303. Fill_Out = CreateThread(NULL,0,FillOutput,0,0,&FillOut);
  304. Play_Out = CreateThread(NULL,0,PlayOutput,0,0,&PlayOut);
  305. Send_In = CreateThread(NULL,0,SendInput,0,0,&SendIn);
  306. }
  307. }
  308. else
  309. {
  310. talk = false;
  311. threadEnd=true;
  312.  
  313. CloseHandle(Fill_In);
  314. CloseHandle(Fill_Out);
  315. CloseHandle(Play_Out);
  316. CloseHandle(Send_In);
  317.  
  318. sound.Stop();
  319.  
  320. SendDlgItemMessage(hwnd,IDOK,WM_SETTEXT,0,(LPARAM)"Push to talk");
  321. }
  322. }
  323. break;
  324. }
  325. break;
  326. default:
  327. return FALSE;
  328. }
  329. return 0;
  330. }
Brent is offline   Reply With Quote
Old Feb 9th, 2008, 10:37 PM   #20
The Dark
Expert Programmer
 
Join Date: Jun 2005
Posts: 816
Rep Power: 4 The Dark is on a distinguished road
Re: Streaming Audio over network

You have two separate queues, input and output, so you will need two separate sets of ReadIndex and WriteIndex. It may even be worth making a queue class so you don't have to have the same code twice.

Also your PLayOutput and SendInput functions both use the variable a without setting a value into it.
The Dark is offline   Reply With Quote
Reply

Bookmarks

« Previous Thread in Forum | Next Thread in Forum »

Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Network Simulator design renato Software Design and Algorithms 2 Dec 11th, 2007 10:54 PM
An Audio and Video class for ruby Master Ruby 3 Mar 24th, 2006 5:49 AM
Streaming audio songs? java_roshan Coder's Corner Lounge 1 Oct 27th, 2005 1:35 PM
Code Request - Onboard Audio Meecher Other Programming Languages 7 Sep 20th, 2005 1:53 AM
Checking source codes of image, audio and video files on_auc C++ 3 Feb 21st, 2005 8:36 PM




DaniWeb IT Discussion Community
All times are GMT -5. The time now is 12:49 AM.

Powered by vBulletin® Version 3.7.0, Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Copyright ©2007 DaniWeb® LLC