{"action":"created","comment":{"url":"https://api.github.com/repos/SFML/SFML/pulls/comments/58311501","id":58311501,"diff_hunk":"@@ -0,0 +1,259 @@\n+////////////////////////////////////////////////////////////\n+//\n+// SFML - Simple and Fast Multimedia Library\n+// Copyright (C) 2007-2016 Laurent Gomila (laurent@sfml-dev.org)\n+//\n+// This software is provided 'as-is', without any express or implied warranty.\n+// In no event will the authors be held liable for any damages arising from the use of this software.\n+//\n+// Permission is granted to anyone to use this software for any purpose,\n+// including commercial applications, and to alter it and redistribute it freely,\n+// subject to the following restrictions:\n+//\n+// 1. The origin of this software must not be misrepresented;\n+//    you must not claim that you wrote the original software.\n+//    If you use this software in a product, an acknowledgment\n+//    in the product documentation would be appreciated but is not required.\n+//\n+// 2. Altered source versions must be plainly marked as such,\n+//    and must not be misrepresented as being the original software.\n+//\n+// 3. This notice may not be removed or altered from any source distribution.\n+//\n+////////////////////////////////////////////////////////////\n+\n+////////////////////////////////////////////////////////////\n+// Headers\n+////////////////////////////////////////////////////////////\n+#include <SFML/Audio/SoundFileWriterOpus.hpp>\n+#include <SFML/System/Err.hpp>\n+#include <algorithm>\n+#include <cstring>\n+#include <ctime>\n+#include <cassert>\n+\n+\n+// Anonymous namespace\n+namespace\n+{\n+    // Make sure to write int into buffer little endian\n+    void writeUint32(unsigned char* buffer, sf::Uint32 value)\n+    {\n+        buffer[0] = static_cast<unsigned char>(value & 0x000000FF);\n+        buffer[1] = static_cast<unsigned char>((value & 0x0000FF00) >> 8);\n+        buffer[2] = static_cast<unsigned char>((value & 0x00FF0000) >> 16);\n+        buffer[3] = static_cast<unsigned char>((value & 0xFF000000) >> 24);\n+    }\n+}\n+\n+namespace sf\n+{\n+namespace priv\n+{\n+////////////////////////////////////////////////////////////\n+bool SoundFileWriterOpus::check(const std::string& filename)\n+{\n+    std::string extension = filename.substr(filename.find_last_of(\".\") + 1);\n+    std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);\n+\n+    return extension == \"opus\";\n+}\n+\n+\n+////////////////////////////////////////////////////////////\n+SoundFileWriterOpus::SoundFileWriterOpus() :\n+m_channelCount (0),\n+m_file         (),\n+m_ogg          (),\n+m_opus         (NULL),\n+m_packageNumber(0)\n+{\n+}\n+\n+\n+////////////////////////////////////////////////////////////\n+SoundFileWriterOpus::~SoundFileWriterOpus()\n+{\n+    close();\n+}\n+\n+\n+////////////////////////////////////////////////////////////\n+bool SoundFileWriterOpus::open(const std::string& filename, unsigned int sampleRate, unsigned int channelCount)\n+{\n+    // Save the channel count\n+    m_channelCount = channelCount;\n+    m_sampleRate = sampleRate;\n+    std::srand(std::time(0));\n+\n+    // Initialize the ogg/opus stream\n+    if (ogg_stream_init(&m_ogg, std::rand()) == -1)\n+    {\n+        err() << \"Stream init of ogg/opus file \\\"\" << filename << \"\\\" failed\" << std::endl;\n+        close();\n+        return false;\n+    }\n+    int status = 0;\n+    m_opus = opus_encoder_create(sampleRate, channelCount, OPUS_APPLICATION_AUDIO, &status);\n+    if (status != OPUS_OK)\n+    {\n+        err() << \"Failed to write ogg/opus file \\\"\" << filename << \"\\\"\" << std::endl;\n+        if (status == OPUS_BAD_ARG)\n+            err() << \"Possible wrong sample rate, allowed are 8000, 12000, 16000, 24000, or 48000 Hz.\" << std::endl;\n+        close();\n+        return false;\n+    }\n+\n+    m_file.open(filename.c_str(), std::ios::binary);\n+    if (!m_file)\n+    {\n+        err() << \"Failed to write ogg/opus file \\\"\" << filename << \"\\\" (cannot open file)\" << std::endl;\n+        close();\n+        return false;\n+    }\n+\n+    // Set bitrate (VBR is default)\n+    opus_encoder_ctl(m_opus, OPUS_SET_BITRATE(128000));\n+\n+    // Create opus header\n+    unsigned char headerData[19];\n+    memset(static_cast<void*>(headerData), 0, 19);\n+    memcpy(static_cast<void*>(headerData), \"OpusHead\", 8);\n+    headerData[8] = 1; // Version\n+    headerData[9] = channelCount;\n+    writeUint32(headerData + 12, static_cast<Uint32>(sampleRate));\n+    headerData[18] = channelCount > 8 ? 255 : (channelCount > 2); // Mapping family\n+\n+    // Map opus header to ogg packet\n+    ogg_packet op;\n+    op.packet = headerData;\n+    op.bytes = 19;\n+    op.b_o_s = 1;\n+    op.e_o_s = 0;\n+    op.granulepos = 0;\n+    op.packetno = m_packageNumber++;\n+\n+    // Write the header packet to the ogg stream\n+    ogg_stream_packetin(&m_ogg, &op);\n+    flushBlocks();\n+\n+    // Create comment header, needs to be in a new page\n+    const char* opusVersion = opus_get_version_string();\n+    Uint32 opusVersionLength = strlen(opusVersion);\n+    const int commentLength  = 8 + 4 + opusVersionLength + 4;\n+\n+    unsigned char commentData[commentLength];","path":"src/SFML/Audio/SoundFileWriterOpus.cpp","position":145,"original_position":145,"commit_id":"99488d368f92a01733d199f5dca842dba60cee79","original_commit_id":"99488d368f92a01733d199f5dca842dba60cee79","user":{"login":"Bromeon","id":708488,"avatar_url":"https://avatars.githubusercontent.com/u/708488?v=3","gravatar_id":"","url":"https://api.github.com/users/Bromeon","html_url":"https://github.com/Bromeon","followers_url":"https://api.github.com/users/Bromeon/followers","following_url":"https://api.github.com/users/Bromeon/following{/other_user}","gists_url":"https://api.github.com/users/Bromeon/gists{/gist_id}","starred_url":"https://api.github.com/users/Bromeon/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Bromeon/subscriptions","organizations_url":"https://api.github.com/users/Bromeon/orgs","repos_url":"https://api.github.com/users/Bromeon/repos","events_url":"https://api.github.com/users/Bromeon/events{/privacy}","received_events_url":"https://api.github.com/users/Bromeon/received_events","type":"User","site_admin":false},"body":"Not allowed in C++, because `commentLength` is not a constant expression. Use `std::vector` instead.","created_at":"2016-04-03T14:53:19Z","updated_at":"2016-04-03T14:53:19Z","html_url":"https://github.com/SFML/SFML/pull/1077#discussion_r58311501","pull_request_url":"https://api.github.com/repos/SFML/SFML/pulls/1077","_links":{"self":{"href":"https://api.github.com/repos/SFML/SFML/pulls/comments/58311501"},"html":{"href":"https://github.com/SFML/SFML/pull/1077#discussion_r58311501"},"pull_request":{"href":"https://api.github.com/repos/SFML/SFML/pulls/1077"}}},"pull_request":{"url":"https://api.github.com/repos/SFML/SFML/pulls/1077","id":65016975,"html_url":"https://github.com/SFML/SFML/pull/1077","diff_url":"https://github.com/SFML/SFML/pull/1077.diff","patch_url":"https://github.com/SFML/SFML/pull/1077.patch","issue_url":"https://api.github.com/repos/SFML/SFML/issues/1077","number":1077,"state":"open","locked":false,"title":"Feature: Opus as additional audio codec","user":{"login":"susnux","id":1855448,"avatar_url":"https://avatars.githubusercontent.com/u/1855448?v=3","gravatar_id":"","url":"https://api.github.com/users/susnux","html_url":"https://github.com/susnux","followers_url":"https://api.github.com/users/susnux/followers","following_url":"https://api.github.com/users/susnux/following{/other_user}","gists_url":"https://api.github.com/users/susnux/gists{/gist_id}","starred_url":"https://api.github.com/users/susnux/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/susnux/subscriptions","organizations_url":"https://api.github.com/users/susnux/orgs","repos_url":"https://api.github.com/users/susnux/repos","events_url":"https://api.github.com/users/susnux/events{/privacy}","received_events_url":"https://api.github.com/users/susnux/received_events","type":"User","site_admin":false},"body":"I was asked to create this PR, so this will add opus as audio codec.\r\nAs described in the [ Forum thread](http://en.sfml-dev.org/forums/index.php?topic=19856.0).\r\n\r\nIf you prefer one commit I can squash them into one.\r\nFeel free to add comments.","created_at":"2016-04-01T23:10:51Z","updated_at":"2016-04-03T14:53:19Z","closed_at":null,"merged_at":null,"merge_commit_sha":"5fd5ff1f63967039471e3f634784d31b14484c89","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/SFML/SFML/pulls/1077/commits","review_comments_url":"https://api.github.com/repos/SFML/SFML/pulls/1077/comments","review_comment_url":"https://api.github.com/repos/SFML/SFML/pulls/comments{/number}","comments_url":"https://api.github.com/repos/SFML/SFML/issues/1077/comments","statuses_url":"https://api.github.com/repos/SFML/SFML/statuses/99488d368f92a01733d199f5dca842dba60cee79","head":{"label":"susnux:feature/opus","ref":"feature/opus","sha":"99488d368f92a01733d199f5dca842dba60cee79","user":{"login":"susnux","id":1855448,"avatar_url":"https://avatars.githubusercontent.com/u/1855448?v=3","gravatar_id":"","url":"https://api.github.com/users/susnux","html_url":"https://github.com/susnux","followers_url":"https://api.github.com/users/susnux/followers","following_url":"https://api.github.com/users/susnux/following{/other_user}","gists_url":"https://api.github.com/users/susnux/gists{/gist_id}","starred_url":"https://api.github.com/users/susnux/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/susnux/subscriptions","organizations_url":"https://api.github.com/users/susnux/orgs","repos_url":"https://api.github.com/users/susnux/repos","events_url":"https://api.github.com/users/susnux/events{/privacy}","received_events_url":"https://api.github.com/users/susnux/received_events","type":"User","site_admin":false},"repo":{"id":40683898,"name":"SFML","full_name":"susnux/SFML","owner":{"login":"susnux","id":1855448,"avatar_url":"https://avatars.githubusercontent.com/u/1855448?v=3","gravatar_id":"","url":"https://api.github.com/users/susnux","html_url":"https://github.com/susnux","followers_url":"https://api.github.com/users/susnux/followers","following_url":"https://api.github.com/users/susnux/following{/other_user}","gists_url":"https://api.github.com/users/susnux/gists{/gist_id}","starred_url":"https://api.github.com/users/susnux/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/susnux/subscriptions","organizations_url":"https://api.github.com/users/susnux/orgs","repos_url":"https://api.github.com/users/susnux/repos","events_url":"https://api.github.com/users/susnux/events{/privacy}","received_events_url":"https://api.github.com/users/susnux/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/susnux/SFML","description":"Simple and Fast Multimedia Library","fork":true,"url":"https://api.github.com/repos/susnux/SFML","forks_url":"https://api.github.com/repos/susnux/SFML/forks","keys_url":"https://api.github.com/repos/susnux/SFML/keys{/key_id}","collaborators_url":"https://api.github.com/repos/susnux/SFML/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/susnux/SFML/teams","hooks_url":"https://api.github.com/repos/susnux/SFML/hooks","issue_events_url":"https://api.github.com/repos/susnux/SFML/issues/events{/number}","events_url":"https://api.github.com/repos/susnux/SFML/events","assignees_url":"https://api.github.com/repos/susnux/SFML/assignees{/user}","branches_url":"https://api.github.com/repos/susnux/SFML/branches{/branch}","tags_url":"https://api.github.com/repos/susnux/SFML/tags","blobs_url":"https://api.github.com/repos/susnux/SFML/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/susnux/SFML/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/susnux/SFML/git/refs{/sha}","trees_url":"https://api.github.com/repos/susnux/SFML/git/trees{/sha}","statuses_url":"https://api.github.com/repos/susnux/SFML/statuses/{sha}","languages_url":"https://api.github.com/repos/susnux/SFML/languages","stargazers_url":"https://api.github.com/repos/susnux/SFML/stargazers","contributors_url":"https://api.github.com/repos/susnux/SFML/contributors","subscribers_url":"https://api.github.com/repos/susnux/SFML/subscribers","subscription_url":"https://api.github.com/repos/susnux/SFML/subscription","commits_url":"https://api.github.com/repos/susnux/SFML/commits{/sha}","git_commits_url":"https://api.github.com/repos/susnux/SFML/git/commits{/sha}","comments_url":"https://api.github.com/repos/susnux/SFML/comments{/number}","issue_comment_url":"https://api.github.com/repos/susnux/SFML/issues/comments{/number}","contents_url":"https://api.github.com/repos/susnux/SFML/contents/{+path}","compare_url":"https://api.github.com/repos/susnux/SFML/compare/{base}...{head}","merges_url":"https://api.github.com/repos/susnux/SFML/merges","archive_url":"https://api.github.com/repos/susnux/SFML/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/susnux/SFML/downloads","issues_url":"https://api.github.com/repos/susnux/SFML/issues{/number}","pulls_url":"https://api.github.com/repos/susnux/SFML/pulls{/number}","milestones_url":"https://api.github.com/repos/susnux/SFML/milestones{/number}","notifications_url":"https://api.github.com/repos/susnux/SFML/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/susnux/SFML/labels{/name}","releases_url":"https://api.github.com/repos/susnux/SFML/releases{/id}","deployments_url":"https://api.github.com/repos/susnux/SFML/deployments","created_at":"2015-08-13T22:06:33Z","updated_at":"2016-04-01T17:32:22Z","pushed_at":"2016-04-03T13:23:59Z","git_url":"git://github.com/susnux/SFML.git","ssh_url":"git@github.com:susnux/SFML.git","clone_url":"https://github.com/susnux/SFML.git","svn_url":"https://github.com/susnux/SFML","homepage":"http://www.sfml-dev.org/","size":76656,"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":"SFML:master","ref":"master","sha":"e00d160224fbdf519aa9e420e57cc8e29e244f31","user":{"login":"SFML","id":4226899,"avatar_url":"https://avatars.githubusercontent.com/u/4226899?v=3","gravatar_id":"","url":"https://api.github.com/users/SFML","html_url":"https://github.com/SFML","followers_url":"https://api.github.com/users/SFML/followers","following_url":"https://api.github.com/users/SFML/following{/other_user}","gists_url":"https://api.github.com/users/SFML/gists{/gist_id}","starred_url":"https://api.github.com/users/SFML/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/SFML/subscriptions","organizations_url":"https://api.github.com/users/SFML/orgs","repos_url":"https://api.github.com/users/SFML/repos","events_url":"https://api.github.com/users/SFML/events{/privacy}","received_events_url":"https://api.github.com/users/SFML/received_events","type":"Organization","site_admin":false},"repo":{"id":1524684,"name":"SFML","full_name":"SFML/SFML","owner":{"login":"SFML","id":4226899,"avatar_url":"https://avatars.githubusercontent.com/u/4226899?v=3","gravatar_id":"","url":"https://api.github.com/users/SFML","html_url":"https://github.com/SFML","followers_url":"https://api.github.com/users/SFML/followers","following_url":"https://api.github.com/users/SFML/following{/other_user}","gists_url":"https://api.github.com/users/SFML/gists{/gist_id}","starred_url":"https://api.github.com/users/SFML/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/SFML/subscriptions","organizations_url":"https://api.github.com/users/SFML/orgs","repos_url":"https://api.github.com/users/SFML/repos","events_url":"https://api.github.com/users/SFML/events{/privacy}","received_events_url":"https://api.github.com/users/SFML/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/SFML/SFML","description":"Simple and Fast Multimedia Library","fork":false,"url":"https://api.github.com/repos/SFML/SFML","forks_url":"https://api.github.com/repos/SFML/SFML/forks","keys_url":"https://api.github.com/repos/SFML/SFML/keys{/key_id}","collaborators_url":"https://api.github.com/repos/SFML/SFML/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/SFML/SFML/teams","hooks_url":"https://api.github.com/repos/SFML/SFML/hooks","issue_events_url":"https://api.github.com/repos/SFML/SFML/issues/events{/number}","events_url":"https://api.github.com/repos/SFML/SFML/events","assignees_url":"https://api.github.com/repos/SFML/SFML/assignees{/user}","branches_url":"https://api.github.com/repos/SFML/SFML/branches{/branch}","tags_url":"https://api.github.com/repos/SFML/SFML/tags","blobs_url":"https://api.github.com/repos/SFML/SFML/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/SFML/SFML/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/SFML/SFML/git/refs{/sha}","trees_url":"https://api.github.com/repos/SFML/SFML/git/trees{/sha}","statuses_url":"https://api.github.com/repos/SFML/SFML/statuses/{sha}","languages_url":"https://api.github.com/repos/SFML/SFML/languages","stargazers_url":"https://api.github.com/repos/SFML/SFML/stargazers","contributors_url":"https://api.github.com/repos/SFML/SFML/contributors","subscribers_url":"https://api.github.com/repos/SFML/SFML/subscribers","subscription_url":"https://api.github.com/repos/SFML/SFML/subscription","commits_url":"https://api.github.com/repos/SFML/SFML/commits{/sha}","git_commits_url":"https://api.github.com/repos/SFML/SFML/git/commits{/sha}","comments_url":"https://api.github.com/repos/SFML/SFML/comments{/number}","issue_comment_url":"https://api.github.com/repos/SFML/SFML/issues/comments{/number}","contents_url":"https://api.github.com/repos/SFML/SFML/contents/{+path}","compare_url":"https://api.github.com/repos/SFML/SFML/compare/{base}...{head}","merges_url":"https://api.github.com/repos/SFML/SFML/merges","archive_url":"https://api.github.com/repos/SFML/SFML/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/SFML/SFML/downloads","issues_url":"https://api.github.com/repos/SFML/SFML/issues{/number}","pulls_url":"https://api.github.com/repos/SFML/SFML/pulls{/number}","milestones_url":"https://api.github.com/repos/SFML/SFML/milestones{/number}","notifications_url":"https://api.github.com/repos/SFML/SFML/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/SFML/SFML/labels{/name}","releases_url":"https://api.github.com/repos/SFML/SFML/releases{/id}","deployments_url":"https://api.github.com/repos/SFML/SFML/deployments","created_at":"2011-03-25T08:05:25Z","updated_at":"2016-04-02T23:38:07Z","pushed_at":"2016-04-03T13:24:00Z","git_url":"git://github.com/SFML/SFML.git","ssh_url":"git@github.com:SFML/SFML.git","clone_url":"https://github.com/SFML/SFML.git","svn_url":"https://github.com/SFML/SFML","homepage":"http://www.sfml-dev.org/","size":77443,"stargazers_count":2716,"watchers_count":2716,"language":"C++","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":603,"mirror_url":null,"open_issues_count":94,"forks":603,"open_issues":94,"watchers":2716,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/SFML/SFML/pulls/1077"},"html":{"href":"https://github.com/SFML/SFML/pull/1077"},"issue":{"href":"https://api.github.com/repos/SFML/SFML/issues/1077"},"comments":{"href":"https://api.github.com/repos/SFML/SFML/issues/1077/comments"},"review_comments":{"href":"https://api.github.com/repos/SFML/SFML/pulls/1077/comments"},"review_comment":{"href":"https://api.github.com/repos/SFML/SFML/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/SFML/SFML/pulls/1077/commits"},"statuses":{"href":"https://api.github.com/repos/SFML/SFML/statuses/99488d368f92a01733d199f5dca842dba60cee79"}}}}