오늘의 네시간짜리 QtMultmedia QAudioInput 뻘짓.

format은 아래와같이

QAudioFormat formatAudio;
formatAudio.setSampleRate(44100);
formatAudio.setChannelCount(2);
formatAudio.setSampleSize(24);
formatAudio.setCodec("audio/pcm");
formatAudio.setByteOrder(QAudioFormat::LittleEndian);
formatAudio.setSampleType(QAudioFormat::SignedInt);

audio device info는 아래와같이

QAudioDeviceInfo getAudioDevice(const QString &name)
{
  foreach(const QAudioDeviceInfo &deviceInfo, QAudioDeviceInfo::availableDevices(QAudio::AudioInput))
  {
    if(deviceInfo.deviceName() == name)
    {
      return deviceInfo;
    }
  }
  return QAudioDeviceInfo();
}

audioDevice = getAudioDevice(“hw:CARD=G5,DEV=0”);

그 후 start하면 iodevice에 어떠한 데이터가 수신되지 않는다. 결론은 이유가 Qt는 24비트 셈플은 S24_LE로 초기화 하기때문이였다.

쉘에서 아래처럼 정보를 확인해보면 지원하는 포맷은 S24_3LE(…)

$ cat /proc/asound/card2/stream0
Creative Technology Ltd Sound BlasterX G5 at usb-3f980000.usb-1.3.1, high speed : USB Audio

Playback:
  Status: Stop
  Interface 1
    Altset 1
    Format: S24_3LE
    Channels: 2
    Endpoint: 1 OUT (ASYNC)
    Rates: 44100, 48000, 88200, 96000
    Data packet interval: 500 us

Capture:
  Status: Stop
  Interface 2
    Altset 1
    Format: S24_3LE
    Channels: 2
    Endpoint: 2 IN (ASYNC)
    Rates: 44100, 48000, 88200, 96000
    Data packet interval: 500 us

좀 더 깔끔하게 코딩하기위해 Qt의 Multmedia를 사용하려했지만 결국 alsa api를 써야할거같다. 아… 왜 저런 차이를 생각하지 못하고 네시간을 삽질했을까… PulseAudio를 활성화 시키면 리셈플링 되어 처리가 가능할거같은데 lite 이미지에서 PulseAudio를 활성화 하는 방법이 구글링되지않아 그건 포기해야겠다.

TV 리모컨으로 USB DAC 볼륨조절

TV의 광 출력 -> USB DAC -> 스피커로 구성 된 환경.
TV가 광으로 소리를 출력할 경우 자체 볼륨조절이 안된다. (PCM출력일 경우 조절 되어서 출력되면 좋을텐데…)

몇번 헛돈을 쓴 끝에 SoundBlasterX G5가 광 입력을 USB 인터페이스와 관계없이 아날로그 출력이 가능하다는것을 알게되어 라즈베리 파이에 IR 수신기를 연결하고 리모컨으로 광 출력의 볼륨을 조절. 단점이있다면 전력 부족인지 정식적으로 리눅스에서 제품이 보장되지 않아서인지 DAC의 초기화가 잘 안된다. USB를 여러번 뽑고 꼽아봐야 인식된다. 라즈베리 파이를 재부팅시키면 USB 전원이 끊어졌다 연결되는데 이 때 인식이 안될경우 약 1분정도 뽑고 다시 꼽으면 대체로 인식되는 듯 하다. (내부 전원이 완전 방전되지 않아서 그런가?) 즉 왠만하면 리즈베리 파이는 끄지 말아야한다(…). 이 부분은 나중에 윈도 10 환경의 라떼판다 제품으로 때워 볼 예정.

일단 이정도로 해놓고 천천히 UI를 제외한 소스코드를 정리해서 올려봐야겠다.

덧.
볼륨조절을 노브(knob)로 돌려서 해야하는 제품은 스피커 볼륨 조절기로 조절하는것과 다를바 없으므로 의미가 없고, 그런 DAC가 아닐경우 보통 USB 인터페이스에서 OS로 신호를 받고 다시 DAC로 전송하는데 이 때 딜레이가 발생한다. 특히 리듬게임을 하면 정확도가 차이날 정도로 딜레이 발생.

덤으로 몇달이나 제품을 찾아봤지만 이 제품만큼의 가격으로 믿을만한 음질에 이런 구성이 가능한 하드웨어를 찾지 못했다. 스피커와 궁합이 꽤나 맞는건지 아날로그 출력도 상당히 만족 중.

WinCrypt의 핸들은 스레드 안정성이 보장안되는거같다

영어가 안되어 크롬의 번역으로 https://stackoverflow.com/a/10807684 이 댓글을 읽어보니…

ECB 모드로 동작할때는 상태가 변경되지않아 상관없으나 기본 모드인 CBC 모드는 상태정보가 변경되기때문에 안정적이지 않다고 이해된다.
이걸 사용하면서 로직 손을 보고나서는 왜 자꾸 패킷이 깨지나했더니 이런거였구나(…) 이거때문에 거의 한달을 미궁에 빠져있었네 orz

복잡하게 처리할거는 없으니 Semaphore를 사용해서 해결해야겠다(…)

참고로 WinCrypt의 사용법 글은 이글의 바로 전 글

AES 256 암호화를 위한 WinCrypt 사용하기

MSDN에서 참고하자니… 너무나도 설명이 장황하고 API 사용에 핵심이되는걸 찾지못하여 example을 구글링하여 여차저차 짜집기하였다. 그중 가장 많은 도움이된 글은 이글이글.

만약 Crypt관련함수들 링크실패하면 헤더나 소스코드에 #pragma comment(lib, "advapi32")를 넣으면된다.

아래는 최소한의 헤더파일

#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <wincrypt.h>

AES 암호화에서 안정성이 보장되는 AES 256을 기준으로 설명한다. 그 하위 AES 암호화는 KEY의 길이가 다르기때문에 필요하다면 32비트 KEY 대신 16비트 키를 사용하면… 될것이다. 나머지는 알고있기로는 동일.

필요한 변수는 아래와같다.

HCRYPTPROV hCryptProv;
HCRYPTHASH hHash;
HCRYPTKEY hKey;

첫번째로 Provider를 얻어야한다.

if (CryptAcquireContext(&hCryptProv, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, 0) == FALSE) {
    return FALSE;
}

핸들을 해제하는 코드는 아래와같다. 이 핸들은 지속적으로 사용하게된다. 완전하게 사용이 끝났으면 그때 Release 해주면된다. Continue reading AES 256 암호화를 위한 WinCrypt 사용하기