Archlinux下声卡的设置与折腾

最近又有瞎折腾装 Arch....发现显卡驱动的安装和设置都不是问题... 声卡却老是出现奇怪的问题,便把最近折腾的经验写下来吧~

# 切换默认声卡

发现最近的新本子基本上声卡设备都不止一个,个人猜测应该是 HDMI 音频输出和 本机主板上的音频输出吧.可以使用 aplay -l 命令显示所有声卡设备. 我机器的输出是:

[acgotaku@Archlinux ~]$ aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: HDMI [HDA Intel HDMI], device 3: HDMI 0 [HDMI 0]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: PCH [HDA Intel PCH], device 0: ALC3220 Analog [ALC3220 Analog]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
1
2
3
4
5
6
7
8

第一个一般为默认的声卡输出设备,显然 HDMI 输出是不对的,导致声音无法正常播放,我们应该把默认声卡切换为 第二个.最简单易用的方法是在用户根目录下新建一个 .asoundrc 文件.输入以下内容:

defaults.pcm.card 1
defaults.pcm.device 0
defaults.ctl.card 1
1
2
3

上面的数据可以从声卡设备输出中找到,这样就切换到 card 1 的 device 0 设备了.不过切换之后可能发现还是没有 声音,因为 alsa 默认是静音的需要手动解除才行. 这就需要去官方源安装 alsamixer 工具. alsa-utils (opens new window) 我自己安装的 alsamixer 使用界面是:

alsamixer

默认 Master 竖条下方显示的不是 00 而是 MM,表示是静音的,按下 m 键解除静音.

# 耳机有持续的杂音的解决方案

有些情况下即使安装好 alsa 解除静音了,但仍然发现戴耳机的时候没有任何软件发声的时候会有持续的杂音,但是音乐播放器一旦放音乐的时候杂音又消失了. 这个问题的原因是 alsa 默认设置 Mic 声道是静音的,我们只需要解除 Mic 声道的静音并调节至合适的值即可.

# 恢复默认的 alsa 设置

有些时候自己胡乱设置导致 alsa 无法正常工作的时候可以通过使用 alsactl restore 命令使 alsa 恢复到默认的配置一般都能正常工作了.

JavaScript中一个经典的正则例子

学习知识的最好方法就是看例子.(个人观点) 因为书上总是会把概念和公式讲的晦涩难懂,才显得作者高大上.所以我总是喜欢 通过例子学习知识.每次写正则的时候总是喜欢查看例子学习如何使用,因为正则实在太耗脑细胞了,记不住,也没必要记住.学会 如何使用并在项目中熟练运用就好了,经常使用的话也就自然记住了.

JavaScript 语言精粹上面有个非常棒的学习例子,每次写正则的时候都会想起它.所以还是记一下分享给大家也方面我查询啦~

var parse_url = /^(?:([A-Za-z]+):)?(\/{0,3})([0-9.\-A-Za-z]+)(?::(\d+))?(?:\/([^?#]*))?(?:\?([^#]*))?(?:#(.*))?$/;
var url = 'http://www.ora.com:80/goodparts?q#fragment';
var result = parse_url.exec(url);
var names = ['url', 'scheme', 'slash', 'host', 'port', 'path', 'query', 'hash'];
var blanks = '     ';
var i;
for (i = 0; i < names.length; i += 1) {
  console.log(names[i] + ':' + blanks.substring(names[i].length), result[i]);
}
1
2
3
4
5
6
7
8
9

让我们分解 parse_url 的各个部分,看看它是如何工作的:

^
1

^字符表示此字符串的开始.它是一个锚,指引 exec 不要跳过那些不像 URL(non-URL-like)的前缀,只匹配那些从开头就像 URL 一样的字符串:

(?:([A-Za-z]+):)?
1

这个因子匹配一个协议名,但仅当它后面跟随一个:(冒号)的时候才匹配.(?:...)表示一个非捕获型分组(noncapturing group). 后缀 ? 表示这个分组是可选的. 问号表示重复 0 次或一次.(...)表示一个捕获型分组(capturing group).一个捕获型分组会复制它 所匹配的文本,并把其放到 result 数组里.每个捕获型分组都会被指定一个编号.第一个捕获型分组的编号是 1,所以该分组所匹配的文本副本 会出现在 result[1]中.[...]表示一个字符类,A-Za-z 这个字符类包含 26 个大写字母和 26 个小写字母.连字符( - )表示范围从 A 到 Z. 后缀 + 表示这个字符类会被匹配一次或者多次.这个组后面跟着字符:,它会按字面进行匹配:

(\/{0,3})
1

下一个因子是捕获型分组 2./表示该匹配/(斜扛).它是\(反斜杠)来进行转义,这样它就不会被错误地解释为这个正则表达式的结束符.后缀{0,3}表示 / 会被匹配 0 次,或者 1~3 次:

([0-9.\-A-Za-z]+)
1

下一个因子是捕获型分组 3.它会匹配一个主机名,由一个或多个数字、字母,以及 . 或 - 字符组成. - 会被转义为 \- 以防止与表示范围的连字符想混淆:

(?::(\d+))?
1

下一个可选的因子匹配端口号,它是由一个前置 : 加上一个或多个数字而组成的序列. \d 表示一个数字字符.一个或多个数字组成的数字串会被捕获型 分组 4 捕获:

(?:\/([^?#]*))?
1

接下来是另一个可选的分组.该分组以一个 / 开始. 之后的字符类[^?#]以一个 ^ 开始, 它表示这个类包含除了?和#之外的所有字符.*表示这个字符类 会被匹配 0 次或多次.

注意这里的处理是不严谨的.这个类匹配除?和#之外的所有字符,其中包括了行结束符、控制字符,以及其他大量不应在此被匹配的字符.大多数情况下,它会按照 我们的预期去做,但某些恶意文本可能会有渗透进来的风险.不严谨的正则表达式是一个常见的安全漏洞发源地.写不严谨的正则表达式比写严谨的正则表达式要容易得多.

(?:\?([^#]*))?
1

接下来,还有一个以一个 ? 开始的可选分组.它包含捕获型分组 6,这个分组包含 0 个或多个非#字符.

(?:#(.*))?
1

最后一个可选分组是以 # 开始的 .会匹配除行结束符以外的所有字符.

$
1

$表示这个字符串的结束.它保证在这个 URL 的尾部没有其他更多内容了.

JavaScript函数中的闭包

JavaScript 中的闭包通常被视作 JavaScript 的高级特性.但是我看了好几次文档也没有明白过来.也没有实际应用过.最近重新学习 JavaScript 打算好好学习下.

# 什么是闭包

闭包用通俗的说法来理解就是子函数可以使用父函数中的局部变量,这种行为叫做闭包.这个变量不是在这个代码块内或者全局上下文中定义的,而是 在定义代码块的环境中定义的(局部变量).一个经典的例子就是:

function a() {
  var i = 0;
  function b() {
    alert(++i);
  }
  return b;
}
var c = a();
c();
1
2
3
4
5
6
7
8
9

函数 b 嵌套在函数 a 内部,函数 a 返回函数 b.这样在执行了 var c = a() 之后,变量 c 变指向了函数 a.再指向 c()就会弹窗显示 i 的值.这段代码就创建了一个 闭包.因为函数 a 外的变量 c 引用了函数 a 内的函数 b.就是说,当函数 a 的内部函数 b 被函数 a 外的一个变量引用的时候,就创建了一个闭包.

# 闭包的用途

  • 可以读取函数内部的变量
  • 这些变量的值始终保持在内存中
  • 模拟私有变量

上面的例子中,i 的值只有 b 函数可以读取.当你不断执行 c()的时候,发现 i 值不断增大,说明 i 没有被内存回收.

# 使用闭包构造模块

模块是一个提供接口却隐藏状态与实现的函数或对象.通过使用函数产生模块,我们几乎可以完全摈弃全局变量的使用. 举例来说,假定我们想要给 String 增加一个 deentityify 方法.它的任务是寻找字符串中的 HTML 字符实体并把它们替换为对应的字符. 这就需要在一个对象中保存字符实体的名字和它们对应的字符.但我们该在哪里保存这个对象呢?我们可以把它放到一个全局变量中, 但全局变量是魔鬼.我们可以把它定义在该函数的内部,但是那会带来运行时的损耗,因为每次执行该函数的时候该字面量都会被求值一次. 理想的方式就是使用闭包实现.

Function.prototype.method = function(name, func) {
  this.prototype[name] = func;
  return this;
};
String.method(
  'deentityify',
  (function() {
    //字符实体表,它映射字符实体打名字到对应的字符.
    var entity = {
      quot: '"',
      lt: '<',
      gt: '>'
    };
    return function() {
      //查找以'&'开头和';'结束打子字符串.如果找到就替换.
      return this.replace(/&([^&;]+);/g, function(a, b) {
        var r = entity[b];
        return typeof r === 'string' ? r : a;
      });
    };
  })()
);
cosole.log('&lt;&quot;&gt;'.deentityify());
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

通过给 Function.prototype 增加一个 method 方法,我们下次给对象增加方法的时候就不必键入 prototype 这几个字符,省掉了麻烦. 请注意最后一行,我们用()运算法立刻调用我们刚刚构造出来的函数.这个调用所创建并返回的函数才是 deentityify 方法.
关于这个的用法请参见 wiki:IIFE (opens new window)

# 闭包的缺点

闭包会使局部变量始终存在,内存消耗很大.在 IE 浏览器中它会很容易导致泄露内存. 还有就是不要在循环中引用闭包.

# 参考资料