ALSA Driver - HW Buffer - Dolinux - Blog Park
ALSA Driver - HW Buffer - Dolinux - Blog Park
dolinux
Linux kernel engineer, computer low-level technology enthusiast
front page manage Essays - 1613 articles - 713 comments - 283 views - 3.27 million
Free AI Assistant
https://www.cnblogs.com/pengdonglin137/articles/12772104.html 1/7
12/29/24, 9:11 PM ALSA driver--HW Buffer - dolinux - Blog Park
Reprinted: https://www.cnblogs.com/fellow1988/p/6204183.html
When the app calls snd_pcm_writei, the alsa core moves the data sent by the app to the HW
buffer (ie, DMA buffer), and the alsa driver reads the data from the HW buffer and transmits
it to the hardware for playback.
ALSA buffer is implemented using ring buffer, which consists of multiple HW buffers.
HW buffer is generally a DMA buffer of size buffer size allocated in the hw_params function
of the alsa driver.
Nickname: dolinux
Age: 12 years The reason why multiple HW buffers are used to form a ring buffer is to prevent the front
Followers: 343 and back positions of the read and write pointers from being frequently swapped (that is,
Following: 54
when the write pointer reaches the HW buffer boundary, it must return to the starting point
+Add Follow
of the HW buffer).
Ring buffer = n * HW buffer. Usually this n is relatively large, and the read and write pointers
search
are rarely swapped during the data reading and writing process.
Look for it
The following figure shows the implementation of ALSA buffer and the method of updating
Google Search
the read and write pointers.
Latest Essays
hw_ptr_base is the starting position of the current HW buffer in the Ring buffer. When the
6. Kernel trouble - How to analyze com
read pointer reaches the end of the HW buffer, hw_ptr_base moves by the buffer size.
plex macro definitions?
hw_ptr is the read pointer of HW buffer. When alsa driver reads data from HW buffer and
7. Use the trace output format of functi sends it to sound card hardware, hw_ptr will move to the new position.
on graph
appl_ptr is the write pointer of HW buffer. When app calls snd_pcm_write to write data, alsa
8. The Linux kernel feature funcgraph-r core copies the data to HW buffer, and appl_ptr is updated.
etaddr I implemented has been merged i
nto Linux 6.13 Boundary is the Ring buffer boundary.
hw_ofs is the position of the read pointer in the current HW buffer, which is returned by
9. Source Insight imports Linux kernel s
pointer() of the alsa driver.
ource code
https://www.cnblogs.com/pengdonglin137/articles/12772104.html 2/7
12/29/24, 9:11 PM ALSA driver--HW Buffer - dolinux - Blog Park
Free
49
50
AI Assistant
pos -= pos % runtime-> min_align;
trace_hwptr(substream, pos, in_interrupt);
51 hw_base = runtime->hw_ptr_base; // Current hw_base 52 new_hw_ptr = hw_ba
https://www.cnblogs.com/pengdonglin137/articles/12772104.html 3/7
12/29/24, 9:11 PM ALSA driver--HW Buffer - dolinux - Blog Park
57 if (delta > new_hw_ptr) { // If this time the interrupt position is added with pe
60 if (hdelta > runtime->hw_ptr_buffer_jiffies/ 2 + 1 ) { // The distance from the l
62 if (hw_base >= runtime-> boundary) {
63 hw_base = 0 ;
64 crossed_boundary++ ;
65 }
66 new_hw_ptr = hw_base + pos;
67 goto __delta;
68 }
69 }
70 }
71 / *
https://www.cnblogs.com/pengdonglin137/articles/12772104.html 4/7
12/29/24, 9:11 PM ALSA driver--HW Buffer - dolinux - Blog Park
110
111 /* something must be really wrong */
112 if (delta >= runtime->buffer_size + runtime->period_size) { // If the curren
113 hw_ptr_error(substream, in_interrupt, " Unexpected hw_ptr " ,
114 " (stream=%i, pos=%ld, new_hw_ptr=%ld, old_hw_ptr=%ld)\n " ,
115 substream->stream, ( long )pos,
116 ( long ) new_hw_ptr, ( long )old_hw_ptr);
117 return
0 ; 118 }
119 120
/
* Do jiffies check
only in xrun_debug mode * /
121 if ( ! BATCH flag.
125 * Such hardware usually just increases the position at each IRQ,
126 * thus it can't give any strange position.
127 */ 128 if (runtime->hw.info & SNDRV_PCM_INFO_BATCH)
129 goto no_jiffies_check;
130 hdelta = delta;
131 if (hdelta < runtime-> delay)
132 goto no_jiffies_check;
133 hdelta -= runtime-> delay;
134 jdelta = curr_jiffies - runtime-> hw_ptr_jiffies;
135 if (((hdelta * HZ) / runtime->rate) > jdelta + HZ/ 100 ) {
136 delta = jdelta /(((runtime->period_size * HZ) / runtime->rate)+ HZ/ 100
137 /* move new_hw_ptr according to jiffies not pos variable */ 138 new_hw_p
139 hw_base = delta;
140 /* use loop to avoid checks for delta overflows */ 141 /* the delta value is sma
143 new_hw_ptr += runtime-> period_size;
144 if (new_hw_ptr >= runtime->
boundary) {
145 new_hw_ptr -= runtime-> boundary;
146 crossed_boundary-- ;
147 }
148 delta-- ;
149 }
150 /* align hw_base to buffer_size */
151 hw_ptr_error(substream, in_interrupt, " hw_ptr skipping " ,
152 " ( pos=%ld, delta=%ld, period=%ld, jdelta=%lu/%lu/%lu, hw_ptr=%ld/%ld)\
153 ( long )pos, ( long )hdelta,
154 ( long )runtime- > period_size, jdelta,
155 ((hdelta * HZ) / runtime-> rate), hw_base,
156 (unsigned long )old_hw_ptr,
157 (unsigned long )new_hw_ptr);
158 /* reset values
to proper state */
159 delta = 0 ;
160 hw_base = new_hw_ptr - (new_hw_ptr % runtime-> buffer_size);
161 }
162 no_jiffies_check:
163 if (delta > runtime->period_size + runtime- >period_size / 2 ) { // interup
164 hw_ptr_error(substream, in_interrupt,
165 " Lost interrupts? " ,
Free AI
166 Assistant
" (stream=%i, delta =%ld, new_hw_ptr=%ld, old_hw_ptr=%ld)\n " ,
167 substream->stream, ( long )delta,
https://www.cnblogs.com/pengdonglin137/articles/12772104.html 5/7
12/29/24, 9:11 PM ALSA driver--HW Buffer - dolinux - Blog Park
168 ( long ;
175 return 0 ;
176 }
177
178 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&runtime->silence_size >
179 snd_pcm_playback_silence(substream, new_hw_ptr); // Play silence
180
181 if (in_interrupt) { // Update hw_ptr_interrupt
182 delta = new_hw_ptr - runtime-> hw_ptr_interrupt;
183 if (delta < 0 )
184 delta += runtime-> boundary;
185 delta -= (snd_pcm_uframes_t)delta % runtime-> period_size;
186 runtime->hw_ptr_interrupt += delta;
187 if (runtime->hw_ptr_interrupt >= runtime-> boundary)
188 runtime->hw_ptr_interrupt -= runtime-> boundary;
189 }
190 runtime->hw_ptr_base = hw_base; // Convert the updated The value is saved t
191 runtime->status->hw_ptr = new_hw_ptr;
192 runtime->hw_ptr_jiffies = curr_jiffies;
193 if (crossed_boundary) {
194 snd_BUG_ON(crossed_boundary != 1 );
195 runtime->hw_ptr_wrap += runtime-> boundary;
196 }
197
198 update_audio_tstamp(substream, &curr_tstamp, & audio_tstamp);
199
200 return snd_pcm_update_state(substream, runtime); // Check whether it is XRUN
201
202
203 }
over.
This article is from Blog Garden, author: dolinux , no reproduction without permission
dolinux
fans - 343 followers - 54 0 0
+Add Follow
Upgrade to Member
Free AI Assistant
posted @ 2020-04-25 11:25 dolinux Read ( 822 ) Comment ( 0 ) Edit Favorite Report
https://www.cnblogs.com/pengdonglin137/articles/12772104.html 6/7
12/29/24, 9:11 PM ALSA driver--HW Buffer - dolinux - Blog Park
Log in to view or post comments, log in now or visit the blog homepage
[Recommendation] A new programming experience, AI that understands you better, try Doubao
MarsCode programming assistant now
[Recommendation] Blog Park joins hands with AI-driven development tool provider Chat2DB to la
unch joint lifetime membership
[Recommendation] Douyin's AI assistant Doubao, your smart encyclopedia, completely free and u
nlimited times
[Recommendation] Lightweight and high-performance SSH tool IShell: AI blessing, one step ahea
d
Editor's recommendation:
· Let's talk about dynamic thread injection of C# thread pool (Part 2)
· How to be a good technical manager
· Kafka's "lock-free philosophy": behind efficient message flow
· The design and implementation of the time wheel in Netty and Kafka
· The implementation principle of MySQL optimization tool SHOW PROFILE
Reading ranking:
· Open source GTKSystem.Windows.Forms framework allows C# Winform to run across platforms
· .NET Bios related data reading and writing
· CSP-J2/S2 2024 travel notes
· Java online car-hailing project practice: detailed explanation of the order grabbing function
· WxPython cross-platform development framework for general printing processing of list data
Today in History:
2014-04-25 Let me popularize the basic knowledge of CPU and SOC to let everyone ma…
2014-04-25 "Embedded Linux Basic Tutorial Study Notes 1"
2014-04-25 "Embedded Linux Basic Tutorial" Supplementary Reading Suggestions Elect…
2013-04-25 A very good program debugging method!
Free AI Assistant
https://www.cnblogs.com/pengdonglin137/articles/12772104.html 7/7