{"action":"created","comment":{"url":"https://api.github.com/repos/googlesamples/android-ndk/pulls/comments/37823278","id":37823278,"diff_hunk":"@@ -0,0 +1,69 @@\n+Echo\n+====\n+The sample demos how to use OpenSL ES to create a player and recorder in Android Fast Audio Path, and connect them to loopback audio. On most android devices, there is a optimized audio path that is tuned up for low latency purpose. The sample creates player/recorder to work in this highly optimized audio path(sometimes called native audio path, [low latency path](http://stackoverflow.com/questions/14842803/low-latency-audio-playback-on-android?rq=1), or fast audio path). The application is validated against the following configurations:\n+  *   Android L    AndroidOne\n+  *   Android M    Nexus 5, Nexus 9\n+\n+Usage\n+-----\n+App will capture audio from android devices and playback on the same device; the playback on speaker will be captured immediately and played back...! So to verify it, it is recommended to \"mute\" the playback audio with a earspeaker/earphone/earbug so it does not get looped back.  Some device like Nexus 9, once you plug in an external headphone/headspeaker, it stops to use onboard microphone AND speaker anymore -- in this case, you need turn on the microphone coming with your headphone. Another point, when switching between external headphone and internal one, the volume is sometimes very low/muted; recommend to increase the playback volume with volume buttons on the phone/pad after plugging external headphone.\n+\n+Low Latency Verification\n+------------------------\n+\n+1. execute \"adb shell dumpsys media.audio_flinger\". Find a list of the running processes\n+    Name Active Client Type      Fmt Chn mask Session fCount S F SRate  L dB  R dB    Server Main buf  Aux Buf Flags UndFrmCnt\n+    F  2     no    704    1 00000001 00000003     562  13248 S 1 48000  -inf  -inf  000033C0 0xabab8480 0x0 0x600         0 \n+    F  5     no    597    1 00000001 00000003     257   6000 A 2 48000    -6    -6  00073B90 0xabab8480 0x0 0x600         0 \n+    F  1     no    597    1 00000001 00000003       9   6000 S 1 48000  -inf  -inf  00075300 0xabab8480 0x0 0x600         0 \n+    F  6    yes   9345    3 00000001 00000001     576    128 A 1 48000     0     0  0376AA00 0xabab8480 0x0 0x400       256 \n+\n+2. execute adb shell ps  | grep echo; find the sample app pid; with the pid, check with result on step 1.: if there is one \"F\" in the front of your echo pid, player is on fast audio path; otherwise, it is not; for fast audio capture[it is totally different story], if you do NOT see \n+    com.example.nativeaudio W/AudioRecord﹕ AUDIO_INPUT_FLAG_FAST denied by client\n+in your logcat output when you create audio recorder, you could \"assume\" you are on the fast path. If your system image was built muted ALOGW, you will not see the above warning message; in which case you would pray and trust [if you created recorder with optimized frequency!].\n+\n+Tune-ups\n+--------\n+A couple of knobs could be used for lower latency purpose. For example, audio buffer size, and how many audio buffers cached before kicking start player: the lower you go with these 2 factors, the lower latency you will have; going with it is the audio processing efficiency demand-- to have a continously playing audio, all processing has to be completed within the capture/playback time for the same amount of the audio frames, minus other software layers' overhead(audio driver, framework, and bufferqueue callbacks etc). Besides that, the irregularity of the buffer queue player/capture callback time -- the assumption of the regularity of evenly distributed callback time need to be highly verified on your interested platforms; the highly tuned up low latency audio path has better chance to \"look\" more regular than other audio paths. Taking iregularity into your consideration, you might have to increase the audio buffer size or caches more buffers between recorder and player. Finding the right trade-off between those factors could be a very interesting experience [alos high efficient code taking very little time to get work done] -- like what it is said \"perfection is a journey\". The knobs in the code are commented accordingly.\n+\n+Credits\n+=======\n+  * The sample is greatly inspired by native-audio sample","path":"echo/README.md","position":null,"original_position":31,"commit_id":"467ffa5941c8295259cd599c0233444fee4c4fc5","original_commit_id":"610f41c9c0b91dc8aece05b154caf01639fcaaef","user":{"login":"proppy","id":5268,"avatar_url":"https://avatars.githubusercontent.com/u/5268?v=3","gravatar_id":"","url":"https://api.github.com/users/proppy","html_url":"https://github.com/proppy","followers_url":"https://api.github.com/users/proppy/followers","following_url":"https://api.github.com/users/proppy/following{/other_user}","gists_url":"https://api.github.com/users/proppy/gists{/gist_id}","starred_url":"https://api.github.com/users/proppy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/proppy/subscriptions","organizations_url":"https://api.github.com/users/proppy/orgs","repos_url":"https://api.github.com/users/proppy/repos","events_url":"https://api.github.com/users/proppy/events{/privacy}","received_events_url":"https://api.github.com/users/proppy/received_events","type":"User","site_admin":false},"body":"But if the new sample was doing:\r\n- recording\r\n- playback\r\n- echo mode\r\nWould that allow use to get rid of `native-audio`?\r\n","created_at":"2015-08-25T01:05:15Z","updated_at":"2015-08-25T01:05:15Z","html_url":"https://github.com/googlesamples/android-ndk/pull/66#discussion_r37823278","pull_request_url":"https://api.github.com/repos/googlesamples/android-ndk/pulls/66","_links":{"self":{"href":"https://api.github.com/repos/googlesamples/android-ndk/pulls/comments/37823278"},"html":{"href":"https://github.com/googlesamples/android-ndk/pull/66#discussion_r37823278"},"pull_request":{"href":"https://api.github.com/repos/googlesamples/android-ndk/pulls/66"}}},"pull_request":{"url":"https://api.github.com/repos/googlesamples/android-ndk/pulls/66","id":43198570,"html_url":"https://github.com/googlesamples/android-ndk/pull/66","diff_url":"https://github.com/googlesamples/android-ndk/pull/66.diff","patch_url":"https://github.com/googlesamples/android-ndk/pull/66.patch","issue_url":"https://api.github.com/repos/googlesamples/android-ndk/issues/66","number":66,"state":"open","locked":false,"title":"Adding Echo: audio loopback with low latency path [fast path]","user":{"login":"ggfan","id":10564521,"avatar_url":"https://avatars.githubusercontent.com/u/10564521?v=3","gravatar_id":"","url":"https://api.github.com/users/ggfan","html_url":"https://github.com/ggfan","followers_url":"https://api.github.com/users/ggfan/followers","following_url":"https://api.github.com/users/ggfan/following{/other_user}","gists_url":"https://api.github.com/users/ggfan/gists{/gist_id}","starred_url":"https://api.github.com/users/ggfan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ggfan/subscriptions","organizations_url":"https://api.github.com/users/ggfan/orgs","repos_url":"https://api.github.com/users/ggfan/repos","events_url":"https://api.github.com/users/ggfan/events{/privacy}","received_events_url":"https://api.github.com/users/ggfan/received_events","type":"User","site_admin":false},"body":"adding one new audio sample to demo fast audio path usage.","created_at":"2015-08-24T17:15:24Z","updated_at":"2015-08-25T01:05:15Z","closed_at":null,"merged_at":null,"merge_commit_sha":"f6d4da8f3683e8ab85d621fcdb56d3855ac1a294","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/googlesamples/android-ndk/pulls/66/commits","review_comments_url":"https://api.github.com/repos/googlesamples/android-ndk/pulls/66/comments","review_comment_url":"https://api.github.com/repos/googlesamples/android-ndk/pulls/comments{/number}","comments_url":"https://api.github.com/repos/googlesamples/android-ndk/issues/66/comments","statuses_url":"https://api.github.com/repos/googlesamples/android-ndk/statuses/467ffa5941c8295259cd599c0233444fee4c4fc5","head":{"label":"ggfan:master","ref":"master","sha":"467ffa5941c8295259cd599c0233444fee4c4fc5","user":{"login":"ggfan","id":10564521,"avatar_url":"https://avatars.githubusercontent.com/u/10564521?v=3","gravatar_id":"","url":"https://api.github.com/users/ggfan","html_url":"https://github.com/ggfan","followers_url":"https://api.github.com/users/ggfan/followers","following_url":"https://api.github.com/users/ggfan/following{/other_user}","gists_url":"https://api.github.com/users/ggfan/gists{/gist_id}","starred_url":"https://api.github.com/users/ggfan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ggfan/subscriptions","organizations_url":"https://api.github.com/users/ggfan/orgs","repos_url":"https://api.github.com/users/ggfan/repos","events_url":"https://api.github.com/users/ggfan/events{/privacy}","received_events_url":"https://api.github.com/users/ggfan/received_events","type":"User","site_admin":false},"repo":{"id":41113673,"name":"android-ndk","full_name":"ggfan/android-ndk","owner":{"login":"ggfan","id":10564521,"avatar_url":"https://avatars.githubusercontent.com/u/10564521?v=3","gravatar_id":"","url":"https://api.github.com/users/ggfan","html_url":"https://github.com/ggfan","followers_url":"https://api.github.com/users/ggfan/followers","following_url":"https://api.github.com/users/ggfan/following{/other_user}","gists_url":"https://api.github.com/users/ggfan/gists{/gist_id}","starred_url":"https://api.github.com/users/ggfan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ggfan/subscriptions","organizations_url":"https://api.github.com/users/ggfan/orgs","repos_url":"https://api.github.com/users/ggfan/repos","events_url":"https://api.github.com/users/ggfan/events{/privacy}","received_events_url":"https://api.github.com/users/ggfan/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/ggfan/android-ndk","description":"Adding Fast Audio Path to Native Audio","fork":true,"url":"https://api.github.com/repos/ggfan/android-ndk","forks_url":"https://api.github.com/repos/ggfan/android-ndk/forks","keys_url":"https://api.github.com/repos/ggfan/android-ndk/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ggfan/android-ndk/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ggfan/android-ndk/teams","hooks_url":"https://api.github.com/repos/ggfan/android-ndk/hooks","issue_events_url":"https://api.github.com/repos/ggfan/android-ndk/issues/events{/number}","events_url":"https://api.github.com/repos/ggfan/android-ndk/events","assignees_url":"https://api.github.com/repos/ggfan/android-ndk/assignees{/user}","branches_url":"https://api.github.com/repos/ggfan/android-ndk/branches{/branch}","tags_url":"https://api.github.com/repos/ggfan/android-ndk/tags","blobs_url":"https://api.github.com/repos/ggfan/android-ndk/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ggfan/android-ndk/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ggfan/android-ndk/git/refs{/sha}","trees_url":"https://api.github.com/repos/ggfan/android-ndk/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ggfan/android-ndk/statuses/{sha}","languages_url":"https://api.github.com/repos/ggfan/android-ndk/languages","stargazers_url":"https://api.github.com/repos/ggfan/android-ndk/stargazers","contributors_url":"https://api.github.com/repos/ggfan/android-ndk/contributors","subscribers_url":"https://api.github.com/repos/ggfan/android-ndk/subscribers","subscription_url":"https://api.github.com/repos/ggfan/android-ndk/subscription","commits_url":"https://api.github.com/repos/ggfan/android-ndk/commits{/sha}","git_commits_url":"https://api.github.com/repos/ggfan/android-ndk/git/commits{/sha}","comments_url":"https://api.github.com/repos/ggfan/android-ndk/comments{/number}","issue_comment_url":"https://api.github.com/repos/ggfan/android-ndk/issues/comments{/number}","contents_url":"https://api.github.com/repos/ggfan/android-ndk/contents/{+path}","compare_url":"https://api.github.com/repos/ggfan/android-ndk/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ggfan/android-ndk/merges","archive_url":"https://api.github.com/repos/ggfan/android-ndk/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ggfan/android-ndk/downloads","issues_url":"https://api.github.com/repos/ggfan/android-ndk/issues{/number}","pulls_url":"https://api.github.com/repos/ggfan/android-ndk/pulls{/number}","milestones_url":"https://api.github.com/repos/ggfan/android-ndk/milestones{/number}","notifications_url":"https://api.github.com/repos/ggfan/android-ndk/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ggfan/android-ndk/labels{/name}","releases_url":"https://api.github.com/repos/ggfan/android-ndk/releases{/id}","created_at":"2015-08-20T18:58:02Z","updated_at":"2015-08-20T18:59:16Z","pushed_at":"2015-08-25T00:41:48Z","git_url":"git://github.com/ggfan/android-ndk.git","ssh_url":"git@github.com:ggfan/android-ndk.git","clone_url":"https://github.com/ggfan/android-ndk.git","svn_url":"https://github.com/ggfan/android-ndk","homepage":"","size":16850,"stargazers_count":0,"watchers_count":0,"language":"C++","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"googlesamples:master","ref":"master","sha":"f81b0d88c24b4bd43a162eade3de0a03f5f08b8f","user":{"login":"googlesamples","id":7378196,"avatar_url":"https://avatars.githubusercontent.com/u/7378196?v=3","gravatar_id":"","url":"https://api.github.com/users/googlesamples","html_url":"https://github.com/googlesamples","followers_url":"https://api.github.com/users/googlesamples/followers","following_url":"https://api.github.com/users/googlesamples/following{/other_user}","gists_url":"https://api.github.com/users/googlesamples/gists{/gist_id}","starred_url":"https://api.github.com/users/googlesamples/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/googlesamples/subscriptions","organizations_url":"https://api.github.com/users/googlesamples/orgs","repos_url":"https://api.github.com/users/googlesamples/repos","events_url":"https://api.github.com/users/googlesamples/events{/privacy}","received_events_url":"https://api.github.com/users/googlesamples/received_events","type":"Organization","site_admin":false},"repo":{"id":35718695,"name":"android-ndk","full_name":"googlesamples/android-ndk","owner":{"login":"googlesamples","id":7378196,"avatar_url":"https://avatars.githubusercontent.com/u/7378196?v=3","gravatar_id":"","url":"https://api.github.com/users/googlesamples","html_url":"https://github.com/googlesamples","followers_url":"https://api.github.com/users/googlesamples/followers","following_url":"https://api.github.com/users/googlesamples/following{/other_user}","gists_url":"https://api.github.com/users/googlesamples/gists{/gist_id}","starred_url":"https://api.github.com/users/googlesamples/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/googlesamples/subscriptions","organizations_url":"https://api.github.com/users/googlesamples/orgs","repos_url":"https://api.github.com/users/googlesamples/repos","events_url":"https://api.github.com/users/googlesamples/events{/privacy}","received_events_url":"https://api.github.com/users/googlesamples/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/googlesamples/android-ndk","description":"","fork":false,"url":"https://api.github.com/repos/googlesamples/android-ndk","forks_url":"https://api.github.com/repos/googlesamples/android-ndk/forks","keys_url":"https://api.github.com/repos/googlesamples/android-ndk/keys{/key_id}","collaborators_url":"https://api.github.com/repos/googlesamples/android-ndk/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/googlesamples/android-ndk/teams","hooks_url":"https://api.github.com/repos/googlesamples/android-ndk/hooks","issue_events_url":"https://api.github.com/repos/googlesamples/android-ndk/issues/events{/number}","events_url":"https://api.github.com/repos/googlesamples/android-ndk/events","assignees_url":"https://api.github.com/repos/googlesamples/android-ndk/assignees{/user}","branches_url":"https://api.github.com/repos/googlesamples/android-ndk/branches{/branch}","tags_url":"https://api.github.com/repos/googlesamples/android-ndk/tags","blobs_url":"https://api.github.com/repos/googlesamples/android-ndk/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/googlesamples/android-ndk/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/googlesamples/android-ndk/git/refs{/sha}","trees_url":"https://api.github.com/repos/googlesamples/android-ndk/git/trees{/sha}","statuses_url":"https://api.github.com/repos/googlesamples/android-ndk/statuses/{sha}","languages_url":"https://api.github.com/repos/googlesamples/android-ndk/languages","stargazers_url":"https://api.github.com/repos/googlesamples/android-ndk/stargazers","contributors_url":"https://api.github.com/repos/googlesamples/android-ndk/contributors","subscribers_url":"https://api.github.com/repos/googlesamples/android-ndk/subscribers","subscription_url":"https://api.github.com/repos/googlesamples/android-ndk/subscription","commits_url":"https://api.github.com/repos/googlesamples/android-ndk/commits{/sha}","git_commits_url":"https://api.github.com/repos/googlesamples/android-ndk/git/commits{/sha}","comments_url":"https://api.github.com/repos/googlesamples/android-ndk/comments{/number}","issue_comment_url":"https://api.github.com/repos/googlesamples/android-ndk/issues/comments{/number}","contents_url":"https://api.github.com/repos/googlesamples/android-ndk/contents/{+path}","compare_url":"https://api.github.com/repos/googlesamples/android-ndk/compare/{base}...{head}","merges_url":"https://api.github.com/repos/googlesamples/android-ndk/merges","archive_url":"https://api.github.com/repos/googlesamples/android-ndk/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/googlesamples/android-ndk/downloads","issues_url":"https://api.github.com/repos/googlesamples/android-ndk/issues{/number}","pulls_url":"https://api.github.com/repos/googlesamples/android-ndk/pulls{/number}","milestones_url":"https://api.github.com/repos/googlesamples/android-ndk/milestones{/number}","notifications_url":"https://api.github.com/repos/googlesamples/android-ndk/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/googlesamples/android-ndk/labels{/name}","releases_url":"https://api.github.com/repos/googlesamples/android-ndk/releases{/id}","created_at":"2015-05-16T10:02:15Z","updated_at":"2015-08-24T11:43:11Z","pushed_at":"2015-08-25T00:41:49Z","git_url":"git://github.com/googlesamples/android-ndk.git","ssh_url":"git@github.com:googlesamples/android-ndk.git","clone_url":"https://github.com/googlesamples/android-ndk.git","svn_url":"https://github.com/googlesamples/android-ndk","homepage":null,"size":17493,"stargazers_count":288,"watchers_count":288,"language":"C++","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":68,"mirror_url":null,"open_issues_count":22,"forks":68,"open_issues":22,"watchers":288,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/googlesamples/android-ndk/pulls/66"},"html":{"href":"https://github.com/googlesamples/android-ndk/pull/66"},"issue":{"href":"https://api.github.com/repos/googlesamples/android-ndk/issues/66"},"comments":{"href":"https://api.github.com/repos/googlesamples/android-ndk/issues/66/comments"},"review_comments":{"href":"https://api.github.com/repos/googlesamples/android-ndk/pulls/66/comments"},"review_comment":{"href":"https://api.github.com/repos/googlesamples/android-ndk/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/googlesamples/android-ndk/pulls/66/commits"},"statuses":{"href":"https://api.github.com/repos/googlesamples/android-ndk/statuses/467ffa5941c8295259cd599c0233444fee4c4fc5"}}}}