• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Android audio system(pcm데이터출력준비-서비스서버)
 

Android audio system(pcm데이터출력준비-서비스서버)

on

  • 1,421 views

 

Statistics

Views

Total Views
1,421
Views on SlideShare
1,201
Embed Views
220

Actions

Likes
0
Downloads
0
Comments
0

4 Embeds 220

http://fefe7270.blogspot.kr 153
http://fefe7270.blogspot.com 61
http://dsync.iptime.org 4
http://www.blogger.com 2

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Android audio system(pcm데이터출력준비-서비스서버) Android audio system(pcm데이터출력준비-서비스서버) Presentation Transcript

    • 안드로이드 아나토미 정리Android Audio System(PCM데이터 출력준비- 서비스 서버) 박철희 1
    • 1.Audio 출력 준비 과정 안드로이드 아나토미 정리AudioFlinger.cppuint32_t AudioFlinger::MixerThread::prepareTracks_l(){ for (size_t i=0 ; i<count ; i++) { sp<Track> t = activeTracks[i].promote(); 활성화 트랙을 가져온다. Track* const track = t.get(); audio_track_cblk_t* cblk = track->cblk(); 활성화 트랙의 컨트롤 블록을 얻어온다. if (cblk->framesReady() && track->isReady() && !track->isPaused() && !track->isTerminated()) { 공유 메모리에 할당할 메모리가 남아 있고, track 이 준비되었다면 mAudioMixer->setBufferProvider(track);  (1)오디오 버퍼 제공자 설정 mAudioMixer->enable(AudioMixer::MIXING);  (2) 트랙의 믹싱 활성화 mAudioMixer->setParameter(AudioMixer::TRACK, AudioMixer::MAIN_BUFFER, (void *)track->mainBuffer()); (3) 메인 버퍼 설정 mAudioMixer->setParameter(AudioMixer::RESAMPLE, AudioMixer::SAMPLE_RATE,(void *)(cblk->sampleRate)); (4)리샘플링 함수 등록 mixerStatus = MIXER_TRACKS_READY;  (5)오디오 믹서 상태 설정 }}(1) mAudioMixer->setBufferProvider(track);  오디오 버퍼 제공자 설정 -오디오 믹서는 활성화된 트랙의 PCM 데이터를 믹싱하기 위해 개별 트랙의 PCM 공유 버퍼에서 데이터를 읽어와야 함. status_t AudioMixer::setBufferProvider(AudioBufferProvider* buffer) AudioBufferProvider { mState.tracks[ mActiveTrack ].bufferProvider = buffer; return NO_ERROR; Trackbase } Track 2
    • 1.Audio 출력 준비 과정 안드로이드 아나토미 정리(2)mAudioMixer->enable(AudioMixer::MIXING);  트랙의 믹싱 활성화 -해당 트랙을 오디오 믹서의 믹싱처리에 추가 한다.(믹싱 함수를 process__validate 로 설정 함.) status_t AudioMixer::enable(int name) { switch (name) { case MIXING: { if (mState.tracks[ mActiveTrack ].enabled != 1) { mState.tracks[ mActiveTrack ].enabled = 1; LOGV("enable(%d)", mActiveTrack); invalidateState(1<<mActiveTrack); } return NO_ERROR; } void AudioMixer::invalidateState(uint32_t mask) { if (mask) { mState.needsChanged |= mask; mState.hook = process__validate; } }(3)mAudioMixer->setParameter(AudioMixer::TRACK,AudioMixer::MAIN_BUFFER, (void *)track->mainBuffer()); audiomixer의 메인 버퍼를 믹서버퍼로 설정 함. status_t AudioMixer::setParameter(int target, int name, void *value) { mState.tracks[ mActiveTrack ].mainBuffer = valueBuf; valuebuf가 playbackThread->mixBuffer();를 의미함. } 3
    • 1.Audio 출력 준비 과정 안드로이드 아나토미 정리(4)(mAudioMixer->setParameter(AudioMixer::RESAMPLE, AudioMixer::SAMPLE_RATE,(void *)(cblk->sampleRate)); - 리샘플링 함수 등록 status_t AudioMixer::setParameter(int target, int name, void *value) { if (track.setResampler(uint32_t(valueInt), mSampleRate)){ invalidateState(1<<mActiveTrack); } return NO_ERROR; } bool AudioMixer::track_t::setResampler(uint32_t value, uint32_t devSampleRate) { if (value!=devSampleRate || resampler) { audiohardware에서 설정된 sameplerate(devSampleRate)와 track의 sample rate(value)가 다를 경우 resampler = AudioResampler::create( format, channelCount, devSampleRate); } Audioresampler.cpp AudioResampler* AudioResampler::create() { pcm 데이터의 음질에 따라 리샘플링을 처리하는 클래스가 결정 됨. switch (quality) { case LOW_QUALITY: resampler = new AudioResamplerOrder1(bitDepth, inChannelCount, sampleRate); break; case MED_QUALITY: resampler = new AudioResamplerCubic(bitDepth, inChannelCount, sampleRate); break; case HIGH_QUALITY: resampler = new AudioResamplerSinc(bitDepth, inChannelCount, sampleRate); break; } 4
    • 1.Audio 출력 준비 과정 안드로이드 아나토미 정리 Audioflinger Audiomixer Mixerthread Buffer provider Mixer buffer MainBuffer AudioTrack++ audiob uffer resamplerandroid write kernel Track[3 32kbyte 1] AudioFlinger::Client (shared memory) 1M Track[0] 5
    • 2.PCM 데이터 리샘플링과 믹싱 안드로이드 아나토미 정리MixerThread::prepareTracks_l() 에서 mixerStatus 가 MIXER_TRACKS_READY 이면리샘플링과 믹싱 과정을 수행한다.bool AudioFlinger::MixerThread::threadLoop(){ if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) { mAudioMixer->process(); } int bytesWritten = (int)mOutput->write(mMixBuffer, mixBufferSize); mixbuffer에 있는 data를 audio driver에 write한다.}void AudioMixer::process(){ mState.hook(&mState);  mState.hook은 process__validate로 설정되어 있음.(invalidateState함수)}void AudioMixer::process__validate(state_t* state){ uint32_t en = state->enabledTracks; 활성화 트랙을 다시 가져온다. while (en) { n |= t.doesResample() ? NEEDS_RESAMPLE_ENABLED : NEEDS_RESAMPLE_DISABLED; 리샘플링 여부 결정 6
    • 2.PCM 데이터 리샘플링과 믹싱 안드로이드 아나토미 정리 믹싱 함수 결정 if (resampling) { state->hook = process__genericResampling; 리샘플링과 믹싱을 동시에 처리 } Else{ state->hook = process__genericNoResampling;  믹싱 처리 if (all16BitsStereoNoResample && !volumeRamp) { if (countActiveTracks == 1) { 오디오 트랙이 하나이면 믹싱처리를 하지 않는 아래 함수가 호출 됨. state->hook = process__OneTrack16BitsStereoNoResampling; } } } state->hook(state);  믹싱 함수 호출 }void AudioMixer::process__OneTrack16BitsStereoNoResampling(){ int32_t* out = t.mainBuffer;  mixerthread의 믹서 버퍼를 out으로 설정한다.while (numFrames) { t.bufferProvider->getNextBuffer(&b); PCM 데이터 공유 버퍼에서 write된 data를 b로 가져온다. *out++ = (r<<16) | (l & 0xFFFF);  가져온 data를 믹서 버퍼로 copy한다. 복사된 데이터는 pcm 데이터 출력 단계에서 소리로 출력 된다. t.bufferProvider->releaseBuffer(&b);  오디오 컨트록 블락에서 server 변수의 값을 갱신한다.} 7
    • 3. PCM 데이터 출력 안드로이드 아나토미 정리bool AudioFlinger::MixerThread::threadLoop(){ if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) { mAudioMixer->process(); 믹서 버퍼에 PCM 데이터가 복사됨. } int bytesWritten = (int)mOutput->write(mMixBuffer, mixBufferSize);} ssize_t AudioHardware::AudioStreamOutMSM72xx::write(const void* buffer, size_t bytes) { size_t count = bytes;  write할 data size const uint8_t* p = static_cast<const uint8_t*>(buffer);  mixer buffer ssize_t written = ::write(mFd, p, count); mFd file descriptor가 가르키는 곳에 mixer buffer의 내용을 write한다. mFd는 status = ::open("/dev/msm_pcm_out", O_WRONLY/*O_RDWR*/); 에 대한 file descriptor이다. if(msm_route_stream(PCM_PLAY, dec_id, DEV_ID(cur_rx), 1)) { LOGE("msm_route_stream failed"); return 0; } ioctrl로 PCM_PLAY 를 driver로 전달해서 play됨. 8