56 |
return 0; |
return 0; |
57 |
} |
} |
58 |
|
|
59 |
|
/* |
60 |
|
* because some cards might have rates "very close", we ignore |
61 |
|
* all "resampling" requests within +-5% |
62 |
|
*/ |
63 |
|
static int rate_match(unsigned int src_rate, unsigned int dst_rate) |
64 |
|
{ |
65 |
|
unsigned int low = (src_rate * 95) / 100; |
66 |
|
unsigned int high = (src_rate * 105) / 100; |
67 |
|
return dst_rate >= low && dst_rate <= high; |
68 |
|
} |
69 |
|
|
70 |
static int snd_pcm_plugin_alloc(snd_pcm_plugin_t *plugin, snd_pcm_uframes_t frames) |
static int snd_pcm_plugin_alloc(snd_pcm_plugin_t *plugin, snd_pcm_uframes_t frames) |
71 |
{ |
{ |
72 |
snd_pcm_plugin_format_t *format; |
snd_pcm_plugin_format_t *format; |
91 |
plugin->buf = vmalloc(size); |
plugin->buf = vmalloc(size); |
92 |
plugin->buf_frames = frames; |
plugin->buf_frames = frames; |
93 |
} |
} |
94 |
if (!plugin->buf) |
if (!plugin->buf) { |
95 |
|
plugin->buf_frames = 0; |
96 |
return -ENOMEM; |
return -ENOMEM; |
97 |
|
} |
98 |
c = plugin->buf_channels; |
c = plugin->buf_channels; |
99 |
if (plugin->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) { |
if (plugin->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) { |
100 |
for (channel = 0; channel < format->channels; channel++, c++) { |
for (channel = 0; channel < format->channels; channel++, c++) { |
101 |
|
c->frames = frames; |
102 |
c->enabled = 1; |
c->enabled = 1; |
103 |
c->wanted = 0; |
c->wanted = 0; |
104 |
c->area.addr = plugin->buf; |
c->area.addr = plugin->buf; |
109 |
snd_assert((size % format->channels) == 0,); |
snd_assert((size % format->channels) == 0,); |
110 |
size /= format->channels; |
size /= format->channels; |
111 |
for (channel = 0; channel < format->channels; channel++, c++) { |
for (channel = 0; channel < format->channels; channel++, c++) { |
112 |
|
c->frames = frames; |
113 |
c->enabled = 1; |
c->enabled = 1; |
114 |
c->wanted = 0; |
c->wanted = 0; |
115 |
c->area.addr = plugin->buf + (channel * size); |
c->area.addr = plugin->buf + (channel * size); |
435 |
|
|
436 |
/* Format change (linearization) */ |
/* Format change (linearization) */ |
437 |
if ((srcformat.format != dstformat.format || |
if ((srcformat.format != dstformat.format || |
438 |
srcformat.rate != dstformat.rate || |
!rate_match(srcformat.rate, dstformat.rate) || |
439 |
srcformat.channels != dstformat.channels) && |
srcformat.channels != dstformat.channels) && |
440 |
!snd_pcm_format_linear(srcformat.format)) { |
!snd_pcm_format_linear(srcformat.format)) { |
441 |
if (snd_pcm_format_linear(dstformat.format)) |
if (snd_pcm_format_linear(dstformat.format)) |
483 |
ttable[v * sv + v] = FULL; |
ttable[v * sv + v] = FULL; |
484 |
} |
} |
485 |
tmpformat.channels = dstformat.channels; |
tmpformat.channels = dstformat.channels; |
486 |
if (srcformat.rate == dstformat.rate && |
if (rate_match(srcformat.rate, dstformat.rate) && |
487 |
snd_pcm_format_linear(dstformat.format)) |
snd_pcm_format_linear(dstformat.format)) |
488 |
tmpformat.format = dstformat.format; |
tmpformat.format = dstformat.format; |
489 |
err = snd_pcm_plugin_build_route(plug, |
err = snd_pcm_plugin_build_route(plug, |
505 |
} |
} |
506 |
|
|
507 |
/* rate resampling */ |
/* rate resampling */ |
508 |
if (srcformat.rate != dstformat.rate) { |
if (!rate_match(srcformat.rate, dstformat.rate)) { |
509 |
tmpformat.rate = dstformat.rate; |
tmpformat.rate = dstformat.rate; |
510 |
if (srcformat.channels == dstformat.channels && |
if (srcformat.channels == dstformat.channels && |
511 |
snd_pcm_format_linear(dstformat.format)) |
snd_pcm_format_linear(dstformat.format)) |