[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-multimedia
Subject:    [PATCH] better fragment count/size setup
From:       Stefan Westerfeld <stefan () space ! twc ! de>
Date:       2000-09-09 18:50:49
[Download RAW message or body]

Hi!

I recently discovered that there is a kernel bug in the OSS/Free driver,
that always gives you one fragment more than requested. The bug is confirmed
by others who have been working with the OSS/Free driver. Unfortunately the
bug isn't there when you are using commercial OSS or ALSA emulation, so
artsd can't really rely on it (and simply subtract one from the desired
fragments) - and maybe it even gets fixed on day for the OSS/Free driver.

Anyway, the impact on the current artsd is the following:

* artsd requests 6 fragments with 8192 bytes
  => it gets 7 fragments with 8192 bytes

... later, after a suspend ...

* artsd requests 7 fragments with 8192 bytes (after all the 6/8192 didn't work)
  => it gets 8 fragments with 8192 bytes

... and so on. This means through repeated suspend/wakeup operations the
buffering time does increase more and more. The patch I attached to fix
this simply will keep on requesting always what the user told the audio
subsystem to request. So it makes the difference between the requested
fragment size and the real fragment size. It will not try to detect the
kernel bug, nor try to workaround it, so the real latencies might still
slightly differ from what you expected on a buggy OSS/Free driver.

There is minor cleanup stuff as well (mainly: allocate the fragment buffer
after we really know how big it should be ;). I'll apply it tomorrow if
there are no objections.

   Cu... Stefan
-- 
  -* Stefan Westerfeld, stefan@space.twc.de (PGP!), Hamburg/Germany
     KDE Developer, project infos at http://space.twc.de/~stefan/kde *-         

["20000909-audiosubsys-fragsize.diff" (text/plain)]

? experimental
Index: audiosubsys.cc
===================================================================
RCS file: /home/kde/kdelibs/arts/flow/audiosubsys.cc,v
retrieving revision 1.22
diff -b -u -p -r1.22 audiosubsys.cc
--- audiosubsys.cc	2000/09/01 22:47:37	1.22
+++ audiosubsys.cc	2000/09/09 18:39:50
@@ -67,6 +67,14 @@ void AudioSubSystemStart::shutdown()
 	delete _instance;
 }
 
+//--- AudioSubSystemPrivate data
+
+struct Arts::AudioSubSystemPrivate
+{
+	int requestedFragmentCount;
+	int requestedFragmentSize;
+};
+
 //--- AudioSubSystem implementation
 
 AudioSubSystem *AudioSubSystem::the()
@@ -79,10 +87,14 @@ const char *AudioSubSystem::error()
 	return _error.c_str();
 }
 
-AudioSubSystem::AudioSubSystem() :_fragmentCount(7), _fragmentSize(1024),
-                                  _samplingRate(44100), _channels(2),
+AudioSubSystem::AudioSubSystem() :_samplingRate(44100), _channels(2),
 								  _fullDuplex(false)
 {
+	d = new AudioSubSystemPrivate;
+
+	fragmentCount(7);
+	fragmentSize(1024);
+
 	_running = false;
 	usageCount = 0;
 	consumer = 0;
@@ -90,6 +102,11 @@ AudioSubSystem::AudioSubSystem() :_fragm
 	fragment_buffer = 0;
 }
 
+AudioSubSystem::~AudioSubSystem()
+{
+	delete d;
+}
+
 bool AudioSubSystem::attachProducer(ASProducer *producer)
 {
 	assert(producer);
@@ -126,7 +143,7 @@ void AudioSubSystem::detachConsumer()
 
 void AudioSubSystem::fragmentCount(int fragmentCount)
 {
-	_fragmentCount = fragmentCount;
+	d->requestedFragmentCount = _fragmentCount = fragmentCount;
 }
 
 int AudioSubSystem::fragmentCount()
@@ -136,7 +153,7 @@ int AudioSubSystem::fragmentCount()
 
 void AudioSubSystem::fragmentSize(int fragmentSize)
 {
-	_fragmentSize = fragmentSize;
+	d->requestedFragmentSize = _fragmentSize = fragmentSize;
 }
 
 int AudioSubSystem::fragmentSize()
@@ -314,13 +331,18 @@ int AudioSubSystem::open()
 		return -1;
 	} 
 
-	// lower 16 bits are the fragment size (as 2^S)
-	// higher 16 bits are the number of fragments
-	int frag_arg = 0;
+	/*
+	 * set the fragment settings to what the user requested
+	 */
 
-	// allocate global buffer to do I/O
-	assert(fragment_buffer == 0);
-	fragment_buffer = new char[_fragmentSize];
+	_fragmentSize = d->requestedFragmentSize;
+	_fragmentCount = d->requestedFragmentCount;
+
+	/*
+	 * lower 16 bits are the fragment size (as 2^S)
+	 * higher 16 bits are the number of fragments
+	 */
+	int frag_arg = 0;
 
 	int size = _fragmentSize;
 	while(size > 1) { size /= 2; frag_arg++; }
@@ -345,8 +367,19 @@ int AudioSubSystem::open()
 		close();
 		return -1;
 	}
-	fragmentSize(info.fragsize);
-	fragmentCount(info.fragstotal);
+
+	// update fragment settings with what we got
+	_fragmentSize = info.fragsize;
+	_fragmentCount = info.fragstotal;
+
+	artsdebug("buffering: %d fragments with %d bytes "
+		"(audio latency is %1.1f ms)\n", _fragmentCount, _fragmentSize,
+		(float)(_fragmentSize*_fragmentCount) /
+		(float)(2.0 * _samplingRate * _channels)*1000.0);
+
+	// allocate global buffer to do I/O
+	assert(fragment_buffer == 0);
+	fragment_buffer = new char[_fragmentSize];
 
 	/*
 	 * Workaround for broken kernel drivers: usually filling up the audio
Index: audiosubsys.h
===================================================================
RCS file: /home/kde/kdelibs/arts/flow/audiosubsys.h,v
retrieving revision 1.10
diff -b -u -p -r1.10 audiosubsys.h
--- audiosubsys.h	2000/08/27 08:14:51	1.10
+++ audiosubsys.h	2000/09/09 18:39:51
@@ -48,8 +48,9 @@ public:
 	void shutdown();
 };
 
+class AudioSubSystemPrivate;
+
 class AudioSubSystem {
-	// unused, added just in case
 	class AudioSubSystemPrivate *d;
 
 	std::string _error;
@@ -70,6 +71,7 @@ class AudioSubSystem {
 
 	friend class AudioSubSystemStart;
 	AudioSubSystem();
+	~AudioSubSystem();
 
 	void close();
 
@@ -139,7 +141,7 @@ public:
 	/*
 	 * returns true as long as the audio subsystem is opened and active (that
 	 * is, between successful opening, with attaching producer, and the first
-	 * detachConsumer/detachProducer
+	 * detachConsumer/detachProducer)
 	 */
 	bool running();
 };

_______________________________________________
Kde-multimedia mailing list
Kde-multimedia@master.kde.org
http://master.kde.org/mailman/listinfo/kde-multimedia


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic