{"action":"created","comment":{"url":"https://api.github.com/repos/kinetiknz/cubeb/pulls/comments/142097866","pull_request_review_id":66410197,"id":142097866,"diff_hunk":"@@ -755,3 +767,89 @@ TEST(cubeb, resampler_passthrough_duplex_callback_reordering)\n \n   cubeb_resampler_destroy(resampler);\n }\n+\n+// Artificially simulate output thread underruns,\n+// by building up artificial delay in the input.\n+// Check that the frame drop logic kicks in.\n+TEST(cubeb, resampler_drift_drop_data) {\n+  cubeb_stream_params input_params;\n+  cubeb_stream_params output_params;\n+\n+  const int input_channels = 1;\n+  const int output_channels = 2;\n+\n+  input_params.channels = input_channels;\n+  input_params.rate = 44100;\n+  input_params.format = CUBEB_SAMPLE_FLOAT32NE;\n+\n+  output_params.channels = output_channels;\n+  output_params.rate = input_params.rate;\n+  output_params.format = CUBEB_SAMPLE_FLOAT32NE;\n+\n+  int target_rate = input_params.rate;\n+\n+  cubeb_resampler * resampler =\n+    cubeb_resampler_create((cubeb_stream*)nullptr, &input_params, &output_params,\n+                           target_rate, cb_passthrough_resampler_duplex, nullptr,\n+                           CUBEB_RESAMPLER_QUALITY_VOIP);\n+\n+  const long BUF_BASE_SIZE = 256;\n+\n+  // The factor by which the deadline is missed. This is intentionally\n+  // kind of large to trigger the frame drop quickly. In real life, multiple\n+  // smaller under-runs would accumulate.\n+  const long UNDERRUN_FACTOR = 6;\n+  float input_buffer_prebuffer[input_channels * BUF_BASE_SIZE * 2];\n+  float input_buffer_glitch[input_channels * BUF_BASE_SIZE * 2 * UNDERRUN_FACTOR];\n+  float input_buffer_normal[input_channels * BUF_BASE_SIZE];\n+  float output_buffer[output_channels * BUF_BASE_SIZE];\n+\n+  long seq_idx = 0;\n+  long output_seq_idx = 0;\n+\n+  long prebuffer_frames = ARRAY_LENGTH(input_buffer_prebuffer) / input_params.channels;\n+  seq_idx = seq(input_buffer_prebuffer, input_channels, seq_idx,\n+                prebuffer_frames);\n+\n+  long got = cubeb_resampler_fill(resampler, input_buffer_prebuffer, &prebuffer_frames,\n+                                  output_buffer, BUF_BASE_SIZE);\n+\n+  output_seq_idx += BUF_BASE_SIZE;\n+\n+  // prebuffer_frames will hold the frames used by the resampler.\n+  ASSERT_EQ(prebuffer_frames, BUF_BASE_SIZE);\n+  ASSERT_EQ(got, BUF_BASE_SIZE);\n+\n+  for (uint32_t i = 0; i < 300; i++) {\n+    long int frames = BUF_BASE_SIZE;","path":"test/test_resampler.cpp","position":86,"original_position":86,"commit_id":"c20c15d665f4ac16f8970ae33c84970f51c5b82d","original_commit_id":"c20c15d665f4ac16f8970ae33c84970f51c5b82d","user":{"login":"padenot","id":270485,"avatar_url":"https://avatars1.githubusercontent.com/u/270485?v=4","gravatar_id":"","url":"https://api.github.com/users/padenot","html_url":"https://github.com/padenot","followers_url":"https://api.github.com/users/padenot/followers","following_url":"https://api.github.com/users/padenot/following{/other_user}","gists_url":"https://api.github.com/users/padenot/gists{/gist_id}","starred_url":"https://api.github.com/users/padenot/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/padenot/subscriptions","organizations_url":"https://api.github.com/users/padenot/orgs","repos_url":"https://api.github.com/users/padenot/repos","events_url":"https://api.github.com/users/padenot/events{/privacy}","received_events_url":"https://api.github.com/users/padenot/received_events","type":"User","site_admin":false},"body":"I need a mutable variable here.","created_at":"2017-10-02T09:56:49Z","updated_at":"2017-10-02T09:56:49Z","html_url":"https://github.com/kinetiknz/cubeb/pull/354#discussion_r142097866","pull_request_url":"https://api.github.com/repos/kinetiknz/cubeb/pulls/354","author_association":"COLLABORATOR","_links":{"self":{"href":"https://api.github.com/repos/kinetiknz/cubeb/pulls/comments/142097866"},"html":{"href":"https://github.com/kinetiknz/cubeb/pull/354#discussion_r142097866"},"pull_request":{"href":"https://api.github.com/repos/kinetiknz/cubeb/pulls/354"}},"in_reply_to_id":141599432},"pull_request":{"url":"https://api.github.com/repos/kinetiknz/cubeb/pulls/354","id":139837392,"html_url":"https://github.com/kinetiknz/cubeb/pull/354","diff_url":"https://github.com/kinetiknz/cubeb/pull/354.diff","patch_url":"https://github.com/kinetiknz/cubeb/pull/354.patch","issue_url":"https://api.github.com/repos/kinetiknz/cubeb/issues/354","number":354,"state":"open","locked":false,"title":"Implement some rudimentary underrun protection for duplex streams","user":{"login":"padenot","id":270485,"avatar_url":"https://avatars1.githubusercontent.com/u/270485?v=4","gravatar_id":"","url":"https://api.github.com/users/padenot","html_url":"https://github.com/padenot","followers_url":"https://api.github.com/users/padenot/followers","following_url":"https://api.github.com/users/padenot/following{/other_user}","gists_url":"https://api.github.com/users/padenot/gists{/gist_id}","starred_url":"https://api.github.com/users/padenot/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/padenot/subscriptions","organizations_url":"https://api.github.com/users/padenot/orgs","repos_url":"https://api.github.com/users/padenot/repos","events_url":"https://api.github.com/users/padenot/events{/privacy}","received_events_url":"https://api.github.com/users/padenot/received_events","type":"User","site_admin":false},"body":"For now, it leaves at most 100ms in the buffer. It seem to behave well. I've used this to test:\r\n\r\n```diff\r\ndiff --git a/test/test_duplex.cpp b/test/test_duplex.cpp\r\nindex 427b503..f17634d 100644\r\n--- a/test/test_duplex.cpp\r\n+++ b/test/test_duplex.cpp\r\n@@ -17,11 +17,14 @@\r\n #include <memory>\r\n #include \"cubeb/cubeb.h\"\r\n #include \"common.h\"\r\n+#include <iostream>\r\n #include <atomic>\r\n\r\n #define SAMPLE_FREQUENCY 48000\r\n #define STREAM_FORMAT CUBEB_SAMPLE_FLOAT32LE\r\n\r\n+static std::atomic<int> rounds = 0;\r\n+\r\n struct user_state_duplex\r\n {\r\n   std::atomic<int> seen_audio{ 0 };\r\n@@ -50,7 +53,11 @@ long data_cb_duplex(cubeb_stream * stream, void * user, const void * inputbuffer\r\n     output_index += 2;\r\n   }\r\n\r\n-  u->seen_audio |= seen_audio;\r\n+  for (uint32_t i = 0; i < nframes * rounds; i++) {\r\n+    if (ib[i % nframes] <= -1.0 && ib[i % nframes] >= 1.0) {\r\n+      u->seen_audio |= seen_audio;\r\n+    }\r\n+  }\r\n\r\n   return nframes;\r\n }\r\n@@ -118,8 +125,13 @@ TEST(cubeb, duplex)\r\n     cleanup_stream_at_exit(stream, cubeb_stream_destroy);\r\n\r\n   cubeb_stream_start(stream);\r\n-  delay(500);\r\n-  cubeb_stream_stop(stream);\r\n+  std::string str;\r\n+  while (getline(std::cin, str)) {\r\n+    std::stringstream iss(str);\r\n+    int temp;\r\n+    iss >> temp;\r\n+    rounds = temp;\r\n+  }\r\n\r\n   ASSERT_TRUE(stream_state.seen_audio.load());\r\n }\r\n\r\n```\r\n\r\nOn my windows machine, I can make it glitch by typing, say, `5000<enter>`, and then bring it back to normal by doing `1000<enter>`.\r\n\r\nIf I backout the actual patch in this PR, delay accumulates between input and output.","created_at":"2017-09-07T15:31:43Z","updated_at":"2017-10-02T09:56:49Z","closed_at":null,"merged_at":null,"merge_commit_sha":"5837114ff0fd4f54cd274d8abc7402f91bc6922b","assignee":null,"assignees":[],"requested_reviewers":[],"milestone":null,"commits_url":"https://api.github.com/repos/kinetiknz/cubeb/pulls/354/commits","review_comments_url":"https://api.github.com/repos/kinetiknz/cubeb/pulls/354/comments","review_comment_url":"https://api.github.com/repos/kinetiknz/cubeb/pulls/comments{/number}","comments_url":"https://api.github.com/repos/kinetiknz/cubeb/issues/354/comments","statuses_url":"https://api.github.com/repos/kinetiknz/cubeb/statuses/c20c15d665f4ac16f8970ae33c84970f51c5b82d","head":{"label":"padenot:underrun","ref":"underrun","sha":"c20c15d665f4ac16f8970ae33c84970f51c5b82d","user":{"login":"padenot","id":270485,"avatar_url":"https://avatars1.githubusercontent.com/u/270485?v=4","gravatar_id":"","url":"https://api.github.com/users/padenot","html_url":"https://github.com/padenot","followers_url":"https://api.github.com/users/padenot/followers","following_url":"https://api.github.com/users/padenot/following{/other_user}","gists_url":"https://api.github.com/users/padenot/gists{/gist_id}","starred_url":"https://api.github.com/users/padenot/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/padenot/subscriptions","organizations_url":"https://api.github.com/users/padenot/orgs","repos_url":"https://api.github.com/users/padenot/repos","events_url":"https://api.github.com/users/padenot/events{/privacy}","received_events_url":"https://api.github.com/users/padenot/received_events","type":"User","site_admin":false},"repo":{"id":8704912,"name":"cubeb","full_name":"padenot/cubeb","owner":{"login":"padenot","id":270485,"avatar_url":"https://avatars1.githubusercontent.com/u/270485?v=4","gravatar_id":"","url":"https://api.github.com/users/padenot","html_url":"https://github.com/padenot","followers_url":"https://api.github.com/users/padenot/followers","following_url":"https://api.github.com/users/padenot/following{/other_user}","gists_url":"https://api.github.com/users/padenot/gists{/gist_id}","starred_url":"https://api.github.com/users/padenot/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/padenot/subscriptions","organizations_url":"https://api.github.com/users/padenot/orgs","repos_url":"https://api.github.com/users/padenot/repos","events_url":"https://api.github.com/users/padenot/events{/privacy}","received_events_url":"https://api.github.com/users/padenot/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/padenot/cubeb","description":"Cross platform audio library","fork":true,"url":"https://api.github.com/repos/padenot/cubeb","forks_url":"https://api.github.com/repos/padenot/cubeb/forks","keys_url":"https://api.github.com/repos/padenot/cubeb/keys{/key_id}","collaborators_url":"https://api.github.com/repos/padenot/cubeb/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/padenot/cubeb/teams","hooks_url":"https://api.github.com/repos/padenot/cubeb/hooks","issue_events_url":"https://api.github.com/repos/padenot/cubeb/issues/events{/number}","events_url":"https://api.github.com/repos/padenot/cubeb/events","assignees_url":"https://api.github.com/repos/padenot/cubeb/assignees{/user}","branches_url":"https://api.github.com/repos/padenot/cubeb/branches{/branch}","tags_url":"https://api.github.com/repos/padenot/cubeb/tags","blobs_url":"https://api.github.com/repos/padenot/cubeb/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/padenot/cubeb/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/padenot/cubeb/git/refs{/sha}","trees_url":"https://api.github.com/repos/padenot/cubeb/git/trees{/sha}","statuses_url":"https://api.github.com/repos/padenot/cubeb/statuses/{sha}","languages_url":"https://api.github.com/repos/padenot/cubeb/languages","stargazers_url":"https://api.github.com/repos/padenot/cubeb/stargazers","contributors_url":"https://api.github.com/repos/padenot/cubeb/contributors","subscribers_url":"https://api.github.com/repos/padenot/cubeb/subscribers","subscription_url":"https://api.github.com/repos/padenot/cubeb/subscription","commits_url":"https://api.github.com/repos/padenot/cubeb/commits{/sha}","git_commits_url":"https://api.github.com/repos/padenot/cubeb/git/commits{/sha}","comments_url":"https://api.github.com/repos/padenot/cubeb/comments{/number}","issue_comment_url":"https://api.github.com/repos/padenot/cubeb/issues/comments{/number}","contents_url":"https://api.github.com/repos/padenot/cubeb/contents/{+path}","compare_url":"https://api.github.com/repos/padenot/cubeb/compare/{base}...{head}","merges_url":"https://api.github.com/repos/padenot/cubeb/merges","archive_url":"https://api.github.com/repos/padenot/cubeb/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/padenot/cubeb/downloads","issues_url":"https://api.github.com/repos/padenot/cubeb/issues{/number}","pulls_url":"https://api.github.com/repos/padenot/cubeb/pulls{/number}","milestones_url":"https://api.github.com/repos/padenot/cubeb/milestones{/number}","notifications_url":"https://api.github.com/repos/padenot/cubeb/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/padenot/cubeb/labels{/name}","releases_url":"https://api.github.com/repos/padenot/cubeb/releases{/id}","deployments_url":"https://api.github.com/repos/padenot/cubeb/deployments","created_at":"2013-03-11T14:16:05Z","updated_at":"2016-07-18T12:10:20Z","pushed_at":"2017-09-27T16:43:49Z","git_url":"git://github.com/padenot/cubeb.git","ssh_url":"git@github.com:padenot/cubeb.git","clone_url":"https://github.com/padenot/cubeb.git","svn_url":"https://github.com/padenot/cubeb","homepage":"","size":2204,"stargazers_count":0,"watchers_count":0,"language":"C++","has_issues":false,"has_projects":true,"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":"kinetiknz:master","ref":"master","sha":"69b9bc88246d4d5280f9ec702e4f5150c06eb358","user":{"login":"kinetiknz","id":67343,"avatar_url":"https://avatars2.githubusercontent.com/u/67343?v=4","gravatar_id":"","url":"https://api.github.com/users/kinetiknz","html_url":"https://github.com/kinetiknz","followers_url":"https://api.github.com/users/kinetiknz/followers","following_url":"https://api.github.com/users/kinetiknz/following{/other_user}","gists_url":"https://api.github.com/users/kinetiknz/gists{/gist_id}","starred_url":"https://api.github.com/users/kinetiknz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kinetiknz/subscriptions","organizations_url":"https://api.github.com/users/kinetiknz/orgs","repos_url":"https://api.github.com/users/kinetiknz/repos","events_url":"https://api.github.com/users/kinetiknz/events{/privacy}","received_events_url":"https://api.github.com/users/kinetiknz/received_events","type":"User","site_admin":false},"repo":{"id":2016094,"name":"cubeb","full_name":"kinetiknz/cubeb","owner":{"login":"kinetiknz","id":67343,"avatar_url":"https://avatars2.githubusercontent.com/u/67343?v=4","gravatar_id":"","url":"https://api.github.com/users/kinetiknz","html_url":"https://github.com/kinetiknz","followers_url":"https://api.github.com/users/kinetiknz/followers","following_url":"https://api.github.com/users/kinetiknz/following{/other_user}","gists_url":"https://api.github.com/users/kinetiknz/gists{/gist_id}","starred_url":"https://api.github.com/users/kinetiknz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kinetiknz/subscriptions","organizations_url":"https://api.github.com/users/kinetiknz/orgs","repos_url":"https://api.github.com/users/kinetiknz/repos","events_url":"https://api.github.com/users/kinetiknz/events{/privacy}","received_events_url":"https://api.github.com/users/kinetiknz/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/kinetiknz/cubeb","description":"Cross platform audio library","fork":false,"url":"https://api.github.com/repos/kinetiknz/cubeb","forks_url":"https://api.github.com/repos/kinetiknz/cubeb/forks","keys_url":"https://api.github.com/repos/kinetiknz/cubeb/keys{/key_id}","collaborators_url":"https://api.github.com/repos/kinetiknz/cubeb/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/kinetiknz/cubeb/teams","hooks_url":"https://api.github.com/repos/kinetiknz/cubeb/hooks","issue_events_url":"https://api.github.com/repos/kinetiknz/cubeb/issues/events{/number}","events_url":"https://api.github.com/repos/kinetiknz/cubeb/events","assignees_url":"https://api.github.com/repos/kinetiknz/cubeb/assignees{/user}","branches_url":"https://api.github.com/repos/kinetiknz/cubeb/branches{/branch}","tags_url":"https://api.github.com/repos/kinetiknz/cubeb/tags","blobs_url":"https://api.github.com/repos/kinetiknz/cubeb/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/kinetiknz/cubeb/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/kinetiknz/cubeb/git/refs{/sha}","trees_url":"https://api.github.com/repos/kinetiknz/cubeb/git/trees{/sha}","statuses_url":"https://api.github.com/repos/kinetiknz/cubeb/statuses/{sha}","languages_url":"https://api.github.com/repos/kinetiknz/cubeb/languages","stargazers_url":"https://api.github.com/repos/kinetiknz/cubeb/stargazers","contributors_url":"https://api.github.com/repos/kinetiknz/cubeb/contributors","subscribers_url":"https://api.github.com/repos/kinetiknz/cubeb/subscribers","subscription_url":"https://api.github.com/repos/kinetiknz/cubeb/subscription","commits_url":"https://api.github.com/repos/kinetiknz/cubeb/commits{/sha}","git_commits_url":"https://api.github.com/repos/kinetiknz/cubeb/git/commits{/sha}","comments_url":"https://api.github.com/repos/kinetiknz/cubeb/comments{/number}","issue_comment_url":"https://api.github.com/repos/kinetiknz/cubeb/issues/comments{/number}","contents_url":"https://api.github.com/repos/kinetiknz/cubeb/contents/{+path}","compare_url":"https://api.github.com/repos/kinetiknz/cubeb/compare/{base}...{head}","merges_url":"https://api.github.com/repos/kinetiknz/cubeb/merges","archive_url":"https://api.github.com/repos/kinetiknz/cubeb/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/kinetiknz/cubeb/downloads","issues_url":"https://api.github.com/repos/kinetiknz/cubeb/issues{/number}","pulls_url":"https://api.github.com/repos/kinetiknz/cubeb/pulls{/number}","milestones_url":"https://api.github.com/repos/kinetiknz/cubeb/milestones{/number}","notifications_url":"https://api.github.com/repos/kinetiknz/cubeb/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/kinetiknz/cubeb/labels{/name}","releases_url":"https://api.github.com/repos/kinetiknz/cubeb/releases{/id}","deployments_url":"https://api.github.com/repos/kinetiknz/cubeb/deployments","created_at":"2011-07-08T04:20:48Z","updated_at":"2017-09-25T08:29:12Z","pushed_at":"2017-09-28T22:12:04Z","git_url":"git://github.com/kinetiknz/cubeb.git","ssh_url":"git@github.com:kinetiknz/cubeb.git","clone_url":"https://github.com/kinetiknz/cubeb.git","svn_url":"https://github.com/kinetiknz/cubeb","homepage":"","size":2468,"stargazers_count":102,"watchers_count":102,"language":"C++","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":40,"mirror_url":null,"open_issues_count":34,"forks":40,"open_issues":34,"watchers":102,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/kinetiknz/cubeb/pulls/354"},"html":{"href":"https://github.com/kinetiknz/cubeb/pull/354"},"issue":{"href":"https://api.github.com/repos/kinetiknz/cubeb/issues/354"},"comments":{"href":"https://api.github.com/repos/kinetiknz/cubeb/issues/354/comments"},"review_comments":{"href":"https://api.github.com/repos/kinetiknz/cubeb/pulls/354/comments"},"review_comment":{"href":"https://api.github.com/repos/kinetiknz/cubeb/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/kinetiknz/cubeb/pulls/354/commits"},"statuses":{"href":"https://api.github.com/repos/kinetiknz/cubeb/statuses/c20c15d665f4ac16f8970ae33c84970f51c5b82d"}},"author_association":"COLLABORATOR"}}
{"actor":{"display_login":"padenot"}}