OSDN Git Service

非同期読み込みを実装した。
authorSFPGMR <sfpg@git.sourceforge.jp>
Thu, 22 Sep 2011 11:18:25 +0000 (20:18 +0900)
committerSFPGMR <sfpg@git.sourceforge.jp>
Thu, 22 Sep 2011 11:18:25 +0000 (20:18 +0900)
13 files changed:
async/application.cpp
async/application.h
async/async.vcxproj
async/async.vcxproj.filters
async/async_reader.cpp
async/async_reader.h
async/audio_source.h [new file with mode: 0644]
async/exception.cpp
async/exception.h
async/toplevel_window.cpp
async/wasapi.cpp
async/wavefile.cpp
async/wavefile.h

index 5e3960e..e450c49 100644 (file)
@@ -33,6 +33,7 @@
 #include "sf_com.h"
 #include "application.h"
 #include "dout.h"
+#include "async_reader.h"
 
 #ifndef HINST_THISCOMPONENT
 EXTERN_C IMAGE_DOS_HEADER __ImageBase;
@@ -44,7 +45,7 @@ using namespace std;
 
 namespace sf {
 #ifdef _DEBUG
-  std::wstring application::app_id_(L"SF.async");
+  std::wstring application::app_id_(L"SF.async_debug");
 #else
   std::wstring application::app_id_(L"SF.async");
 #endif
@@ -181,6 +182,7 @@ namespace sf {
               if(!not_enqueue_){              
                 uint32_t size = reader_->data_bytes_remaining() >  wasapi_->get_buffer_byte_size() ?  wasapi_->get_buffer_byte_size() : reader_->data_bytes_remaining();
                 reader_->read_data(read_buffer_[read_index_].get(),sizeof(uint8_t) * size);
+                reader_->wait();
                 if(size < wasapi_->get_buffer_byte_size())
                 {
                   memset(read_buffer_[read_index_].get() + size,0,wasapi_->get_buffer_byte_size() - size);
@@ -198,7 +200,7 @@ namespace sf {
                   }
                   break;
                 } else {
-                  Sleep(0);
+                  Sleep(1);
                 }
               }
 
@@ -241,7 +243,7 @@ namespace sf {
         output_counter_ = 0;
         break;
       }
-      Sleep(0);
+      Sleep(1);
 //      wdout << L"reader_threadは起動中" << std::endl;
     }
 loop_end:
@@ -253,6 +255,7 @@ loop_end:
   /// WASAPI出力スレッド
   void application::output_thread_main()
   {
+    {
     // COMの初期化
     sf::com_initialize init();
 
@@ -320,13 +323,15 @@ loop_end:
 #ifdef _DEBUG
     wdout << L"***** output_threadは終了!" << std::endl;
 #endif
+    ;}
 ;  };
 
   void application::setup(const std::wstring& file_path)
   {
     try {
       source_file_path_ = file_path;
-      reader_.reset(new wave_file_reader(file_path,false));
+//      reader_.reset(new wave_file_reader(file_path,false));
+      reader_.reset(new async_reader(file_path,false));
       wasapi_.reset(new sf::wasapi_shared_timer(reader_->get_wave_format()));
       if(!wasapi_->is_enabled())
       {
index bebc00f..00e9c6d 100644 (file)
@@ -25,7 +25,7 @@
 #include "exception.h"
 #include "ring_buffer.h"
 #include "wasapi.h"
-#include "wavefile.h"
+#include "async_reader.h"
 #include "sf_memory.h"
 #include "toplevel_window.h"
 
@@ -89,7 +89,7 @@ private:
   boost::thread reader_thread_;
   handle_holder event_reader_;
   std::wstring source_file_path_;
-  std::unique_ptr<wave_file_reader> reader_;
+  std::unique_ptr<async_reader> reader_;
   sf::buffer_t read_buffer_;
   uint32_t read_index_;
   uint64_t read_position_;
index 4887420..dc90bd2 100644 (file)
     <ClInclude Include="application.h" />
     <ClInclude Include="async_reader.h" />
     <ClInclude Include="audio_base.h" />
+    <ClInclude Include="audio_source.h" />
     <ClInclude Include="base_window.h" />
     <ClInclude Include="code_converter.h" />
     <ClInclude Include="dout.h" />
index c7165a3..eb0d819 100644 (file)
     <ClInclude Include="ring_buffer.h">
       <Filter>ヘッダー ファイル</Filter>
     </ClInclude>
+    <ClInclude Include="audio_source.h">
+      <Filter>ヘッダー ファイル</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="async.rc">
index 106d485..b15c4c6 100644 (file)
 /*
-  ==============================================================================
+==============================================================================
 
-   This file is part of the async
-   Copyright 2005-10 by Satoshi Fujiwara.
+This file is part of the async
+Copyright 2005-11 by Satoshi Fujiwara.
 
-   async can be redistributed and/or modified under the terms of the
-   GNU General Public License, as published by the Free Software Foundation;
-   either version 2 of the License, or (at your option) any later version.
+async can be redistributed and/or modified under the terms of the
+GNU General Public License, as published by the Free Software Foundation;
+either version 2 of the License, or (at your option) any later version.
 
-   async is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
+async is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
 
-   You should have received a copy of the GNU General Public License
-   along with async; if not, visit www.gnu.org/licenses or write to the
-   Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
-   Boston, MA 02111-1307 USA
+You should have received a copy of the GNU General Public License
+along with async; if not, visit www.gnu.org/licenses or write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
+Boston, MA 02111-1307 USA
 
-  ==============================================================================
+==============================================================================
 */
+
+// SDK\82Ì\83T\83\93\83v\83\8b\82ð\89ü\91¢\82µ\82½\8dì\82Á\82½\82à\82Ì\81B\93à\97e\82Í\82Ù\82Ú\82»\82Ì\82Ü\82Ü\82¾\82ª\81A\94ñ\93¯\8aú\93Ç\82Ý\8d\9e\82Ý\82É
+// \91Î\89\9e\82³\82¹\82½\81B
+
+#include "stdafx.h"
+#if _DEBUG
+#define _CRTDBG_MAP_ALLOC
+#include <crtdbg.h>
+#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
+#endif
+#include <stdio.h>
+#include <assert.h>
+#include <wtypes.h>
+#include <mmreg.h>
+#include <ks.h>
+#include <ksmedia.h>
 #include "stdafx.h"
 #include "async_reader.h"
+using namespace std;
+
+namespace sf
+{
+  typedef struct
+  {
+    ULONG Riff4CC;      // "RIFF" 4-character code
+    ULONG FileSize;     // total file size in bytes
+    ULONG Wave4CC;      // "WAVE" 4-character code
+    ULONG Fmt4CC;       // "fmt " 4-character code
+    ULONG FormatSize;   // wave format size in bytes
+  } FileHeader;
+
+  typedef struct
+  {
+    ULONG ChunkType;
+    ULONG ChunkSize;
+  } ChunkHeader;
+
+  // Any file smaller than this cannot possibly contain wave data.
+#define MIN_WAVE_FILE_SIZE (sizeof(FileHeader)+sizeof(PCMWAVEFORMAT)+sizeof(ChunkHeader)+1)
+
+  // Macro to build FOURCC from first four characters in ASCII string
+#define FOURCC(s)  ((ULONG)(s[0] | (s[1]<<8) | (s[2]<<16) | (s[3]<<24)))
+
+  //
+  // Constructor -- Open wave file and parse file header.
+  //
+  async_reader::async_reader(const std::wstring file_name, bool repeat_mode) 
+    : 
+    stream_status_(false),
+    data_chunk_position(0),
+    total_data_bytes_(0),
+    data_bytes_remaining_(0),
+    offset_(0),
+    repeat_mode_(false),
+    async_reading_(false)
+  {
+
+    // \83C\83x\83\93\83g\83I\83u\83W\83F\83N\83g\82Ì\8f\89\8aú\89»
+    ZeroMemory(&wfx_, sizeof(wfx_));
+    event_.reset(::CreateEventEx(NULL, NULL, CREATE_EVENT_MANUAL_RESET, EVENT_MODIFY_STATE | SYNCHRONIZE));
+
+    // OVERLAPPED\8d\\91¢\91Ì\82Ì\8f\89\8aú\89»
+    ZeroMemory(&overlapped_,sizeof(overlapped_));
+    overlapped_.hEvent = event_.get();
+
+
+    try{
+      // \83t\83@\83C\83\8b\83I\81[\83v\83\93
+      file_.reset(CreateFile(file_name.c_str(),GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_READONLY | FILE_FLAG_OVERLAPPED,NULL));
+      if(file_.get() == INVALID_HANDLE_VALUE)
+      {
+        throw win32_error_exception(GetLastError());
+      }
+
+      // \83t\83@\83C\83\8b\83w\83b\83_\82Ì\93Ç\82Ý\8d\9e\82Ý
+      FileHeader fileHdr;
+      read_data_sync(reinterpret_cast<BYTE*>(&fileHdr),sizeof(fileHdr));
+
+      // \83w\83b\83_\82Ì\83`\83F\83b\83N
+      if (fileHdr.Riff4CC != FOURCC("RIFF") ||
+        fileHdr.FileSize < MIN_WAVE_FILE_SIZE ||
+        fileHdr.Wave4CC != FOURCC("WAVE") ||
+        fileHdr.Fmt4CC != FOURCC("fmt ") ||
+        fileHdr.FormatSize < sizeof(PCMWAVEFORMAT))
+      {
+        throw file_error_exception(std::wstring(L"\95s\96¾\82È.WAV\83t\83@\83C\83\8b\83t\83H\81[\83}\83b\83g\82Å\82·\81B"));
+      }
+
+      // \83t\83H\81[\83}\83b\83g\83f\83X\83N\83\8a\83v\83^\82Ì\93Ç\82Ý\8d\9e\82Ý
+      read_data_sync(reinterpret_cast<BYTE*>(&wfx_),min(fileHdr.FormatSize,sizeof(wfx_)));
+      //offset += min(fileHdr.FormatSize,sizeof(wfx_));
+
+      // Skip over any padding at the end of the format in the format chunk.
+      if (fileHdr.FormatSize > sizeof(wfx_))
+      {
+        offset_ += (fileHdr.FormatSize - sizeof(wfx_));
+      }
+
+      // If format type is PCMWAVEFORMAT, convert to valid WAVEFORMATEX structure.
+      if (wfx_.Format.wFormatTag == WAVE_FORMAT_PCM)
+      {
+        wfx_.Format.cbSize = 0;
+      }
+
+      // If format type is WAVEFORMATEX, convert to WAVEFORMATEXTENSIBLE.
+      if (wfx_.Format.wFormatTag == WAVE_FORMAT_PCM ||
+        wfx_.Format.wFormatTag == WAVE_FORMAT_IEEE_FLOAT)
+      {
+        if (wfx_.Format.wFormatTag == WAVE_FORMAT_PCM)
+        {
+          wfx_.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
+        }
+        else
+        {
+          wfx_.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
+        }
+        wfx_.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
+
+        // Note that the WAVEFORMATEX structure is valid for
+        // representing wave formats with only 1 or 2 channels.
+        if (wfx_.Format.nChannels == 1)
+        {
+          wfx_.dwChannelMask = SPEAKER_FRONT_CENTER;
+        }
+        else if (wfx_.Format.nChannels == 2)
+        {
+          wfx_.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
+        }
+        else
+        {
+          throw file_error_exception(std::wstring(L"\83T\83|\81[\83g\82µ\82Ä\82¢\82È\82¢.WAV\83t\83@\83C\83\8b\82Å\82·\81B"));
+        }
+        wfx_.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
+        wfx_.Samples.wValidBitsPerSample = wfx_.Format.wBitsPerSample;
+      }
+
+      // This wave file reader understands only PCM and IEEE float formats.
+      if (wfx_.Format.wFormatTag != WAVE_FORMAT_EXTENSIBLE ||
+        wfx_.SubFormat != KSDATAFORMAT_SUBTYPE_PCM &&
+        wfx_.SubFormat != KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)
+      {
+        throw file_error_exception(std::wstring(L"\83T\83|\81[\83g\82µ\82Ä\82¢\82È\82¢.WAV\83t\83@\83C\83\8b\82Å\82·\81B"));
+      }
+
+      // \83f\81[\83^\83`\83\83\83\93\83N\82ð\8c\9f\8dõ\82·\82é\81B\82»\82Ì\91¼\82Ì\83`\83\83\83\93\83N\82Í\93Ç\82Ý\94ò\82Î\82·\81B
+      ChunkHeader chunkHdr;   /// \83`\83\83\83\93\83N\83w\83b\83_
+      for (;;)
+      {
+        // Read header at start of next chunk of file.
+        data_chunk_position = offset_;
+        read_data_sync(reinterpret_cast<BYTE*>(&chunkHdr),sizeof(ChunkHeader));
+        if (chunkHdr.ChunkType == FOURCC("data"))
+        {
+          break;  // found start of data chunk
+        }
+      }
+
+      // We've found the start of the data chunk. We're ready to start
+      // playing wave data...
+      total_data_bytes_ = chunkHdr.ChunkSize;
+      data_bytes_remaining_ = total_data_bytes_;
+      if (total_data_bytes_ == 0)
+      {
+        throw file_error_exception(std::wstring(L"\83t\83@\83C\83\8b\83T\83C\83Y\82ª\95s\90³\82Å\82·\81B"));
+      }
+      stream_status_ = true;
+    } catch (exception& e) {
+      stream_status_ = false;
+      throw;
+    }
+  }
+
+  //
+  // Destructor
+  //
+  async_reader::~async_reader()
+  {
+    // \8ec\82Á\82Ä\82¢\82éI/O\82Í\83L\83\83\83\93\83Z\83\8b\82·\82é
+    if(async_reading_){
+      DWORD numbytes_copied;
+      DWORD res = GetOverlappedResult(file_.get(),&overlapped_,(LPDWORD)&numbytes_copied,FALSE);
+      if(!res)
+      {
+        switch(GetLastError())
+        {
+        case ERROR_IO_INCOMPLETE:
+        case ERROR_IO_PENDING:
+          ::CancelIoEx(file_.get(),&overlapped_);
+          WaitForSingleObject(event_.get(),INFINITE);
+          break;
+        }
+      }
+    }
+    
+    // \83t\83@\83C\83\8b\82ð\83N\83\8d\81[\83Y\82·\82é
+    if (file_)
+    {
+      file_.release();
+      //      fclose(file_);
+    }
+  }
+
+  //
+  // Reset the file pointer to the start of the wave data.
+  //
+  void async_reader::reset_data_position()
+  {
+    if (!stream_status_ )
+    {
+      throw file_error_exception(std::wstring(L"\83t\83@\83C\83\8b\82ª\83I\81[\83v\83\93\82³\82ê\82Ä\82¢\82Ü\82¹\82ñ\81B"));
+    }
+
+    // Read the header for the data chunk.
+    ChunkHeader chunkHdr;
+    offset_ = data_chunk_position;
+    read_data_sync(reinterpret_cast<BYTE*>(&chunkHdr),sizeof(chunkHdr));
 
-namespace sf{
+    // Sanity check: The chunk header shouldn't have changed.
+    if (chunkHdr.ChunkType != FOURCC("data") ||
+      chunkHdr.ChunkSize != total_data_bytes_)
+    {
+      throw file_error_exception(std::wstring(L"\95s\90³\82ÈWAV\83t\83@\83C\83\8b\82Å\82·\81B"));
+    }
 
-// async_reader::impl\83N\83\89\83X\82Ì\8eÀ\91\95
+    data_bytes_remaining_ = total_data_bytes_;
 
-  struct async_reader::impl {
+  }
+
+  void async_reader::seek(uint64_t pos)
+  {
+    if (!stream_status_ )
+    {
+      throw file_error_exception(std::wstring(L"\83t\83@\83C\83\8b\82ª\83I\81[\83v\83\93\82³\82ê\82Ä\82¢\82Ü\82¹\82ñ\81B"));
+    }
+    pos = (pos / get_wave_format().Format.nBlockAlign) * get_wave_format().Format.nBlockAlign;
+    data_bytes_remaining_ = total_data_bytes_ - pos;
+    offset_ = pos + data_chunk_position + sizeof(ChunkHeader);
+    overlapped_.Pointer = (PVOID)pos;
+  }
+
+
+  //
+  // Load next block of wave data from file into playback buffer.
+  // In repeat mode, when we reach the end of the wave data in the
+  // file, we just reset the file pointer back to the start of the
+  // data and continue filling the caller's buffer until it is full.
+  // In single-play mode, once we reach the end of the wave data in
+  // the file, we just fill the buffer with silence instead of with
+  // real data.
+  //
+  void async_reader::read_data(BYTE *buffer, uint64_t numbytes_to_copy)
+  {
+    assert(async_reading_ == false);
+
+    if (!stream_status_ )
+    {
+      throw file_error_exception(std::wstring(L"\83t\83@\83C\83\8b\82ª\83I\81[\83v\83\93\82³\82ê\82Ä\82¢\82Ü\82¹\82ñ\81B"));
+    }
+
+    if (buffer == NULL)
+    {
+      throw file_error_exception(L"\83o\83b\83t\83@\83A\83h\83\8c\83X\82ª\96³\8cø\82Å\82·\81B");
+    }
+
+    if (numbytes_to_copy == 0)
+    {
+      throw file_error_exception(L"\93Ç\82Ý\8d\9e\82Ý\83o\83C\83g\90\94\82Ì\8ew\92è\82ª0\82Å\82·\81B");
+    }
+
+    ULONG numbytes_copied;
+    overlapped_.Pointer = (PVOID)offset_;
+    int result = ReadFile(file_.get(),buffer,numbytes_to_copy,&numbytes_copied,&overlapped_);
+    if(!result)
+    {
+      DWORD err = GetLastError(); 
+      switch(err)
+      {
+      case ERROR_HANDLE_EOF:
+        {
+          if(numbytes_to_copy > numbytes_copied)
+          {
+            BYTE silence = (wfx_.Format.wBitsPerSample==8) ? 0x80 : 0;
+            memset(buffer + numbytes_copied, silence, numbytes_to_copy - numbytes_copied);
+          }
+          offset_ += numbytes_copied; 
+          async_reading_ = false;
+          throw file_eof_exception(std::wstring(L"\83t\83@\83C\83\8b\82Ì\8fI\82í\82è\82É\92B\82µ\82½\82½\82ß\81A\83w\83b\83_\82ð\93Ç\82Ý\8d\9e\82Þ\82±\82Æ\82ª\82Å\82«\82Ü\82¹\82ñ\81B"));
+        }
+        break;
+      case ERROR_IO_PENDING:
+        //{
+        //  DWORD res = GetOverlappedResult(file_.get(),&overlapped_,&num_of_read,TRUE);
+        //  if(!res)
+        //  {
+        //    throw file_error_exception(win32_error_exception::get_last_error_str());
+        //  } else {
+        //    if(res != numbytes_to_copy)
+        //    {
+        //      throw file_error_exception(std::wstring(L"\93Ç\82Ý\8d\9e\82ñ\82¾\83f\81[\83^\83T\83C\83Y\82ª\8d\87\82¢\82Ü\82¹\82ñ\81B"));
+        //    }
+        //  }
+        //}
+        async_reading_ = true;
+        break;
+      default:
+        throw file_error_exception(win32_error_exception::get_last_error_str(err));
+        break;
+      }
+    } else {
+      data_bytes_remaining_ -= data_chunk_position;
+      offset_ += data_chunk_position;
+      async_reading_ = false;
+      //current += numbytes_copied;
+    }
+
+
+    //if(numbytes_copied > data_bytes_remaining_)
+    //{
+    //  if (fread(current, 1, data_bytes_remaining_, file_) != data_bytes_remaining_)
+    //  {
+    //    throw exception(L"\95s\90³\82ÈWAV\83t\83@\83C\83\8b\82Å\82·\81B");
+    //  }
+    //  current += data_bytes_remaining_;
+    //  numbytes_copied -= data_bytes_remaining_;
+    //  data_bytes_remaining_ = 0;
+
+    //  // The file pointer now sits at the end of the data chunk.
+    //  // Are we operating in repeat mode?
+    //  if (!repeat_mode_)
+    //  {
+    //    // Nope, we're operating in single-play mode. Fill
+    //    // the rest of the buffer with silence and return.
+    //    BYTE silence = (wfx_.Format.wBitsPerSample==8) ? 0x80 : 0;
+    //    memset(current, silence, numbytes_copied);
+    //    return;  // yup, we're done
+    //  }
+    //  // Yes, we're operating in repeat mode, so loop back to
+    //  // the start of the wave data in the file's data chunk
+    //  // and continue loading data into the caller's buffer.
+    //  reset_data_position();
+
+    //}
+
+    //assert(numbytes_copied > 0);
+    //assert(numbytes_copied <= data_bytes_remaining_);
+
+    //// The remainder of the data chunk is big enough to
+    //// completely fill the remainder of the caller's buffer.
+    //if (fread(buffer, 1, numbytes_copied, file_) != numbytes_copied)
+    //{
+    //  throw exception(L"\95s\90³\82ÈWAV\83t\83@\83C\83\8b\82Å\82·\81B");
+    //}
+    //data_bytes_remaining_ -= numbytes_copied;
+    //current += numbytes_copied;
+  }
+
+  void async_reader::read_data_sync(BYTE *buffer, uint64_t numbytes_to_copy)
+  {
+    uint32_t numbytes_copied(0);
+    overlapped_.Pointer = (PVOID)offset_;
+
+    int result = ReadFile(file_.get(),buffer, numbytes_to_copy, (LPDWORD)&numbytes_copied, &overlapped_);
+
+    if(!result)
+    {
+      uint32_t err = GetLastError(); 
+      switch(err)
+      {
+      case ERROR_HANDLE_EOF:
+        {
+          offset_ += numbytes_copied;
+          if(repeat_mode_){
+            reset_data_position();
+          }
+          throw file_eof_exception(std::wstring(L"\83t\83@\83C\83\8b\82Ì\8fI\82í\82è\82É\92B\82µ\82½\82½\82ß\81A\83w\83b\83_\82ð\93Ç\82Ý\8d\9e\82Þ\82±\82Æ\82ª\82Å\82«\82Ü\82¹\82ñ\81B"));
+        }
+        break;
+      case ERROR_IO_PENDING:
+        {
+          DWORD res = GetOverlappedResult(file_.get(),&overlapped_,(LPDWORD)&numbytes_copied,TRUE);
+          if(!res)
+          {
+            throw file_error_exception(win32_error_exception::get_last_error_str());
+          } else {
+            if(numbytes_copied != numbytes_to_copy)
+            {
+              throw file_error_exception(std::wstring(L"\93Ç\82Ý\8d\9e\82ñ\82¾\83f\81[\83^\83T\83C\83Y\82ª\8d\87\82¢\82Ü\82¹\82ñ\81B"));
+            }
+            offset_ += numbytes_copied;
+          }
+        }
+        break;
+      default:
+          throw file_error_exception(win32_error_exception::get_last_error_str(err));
+        break;
+      }
+    } else {
+      offset_ += numbytes_copied;
+    }
   };
-async_reader::async_reader() : impl_(new impl())
-{
-}
 
-async_reader::~async_reader()
-{
-}
+  void async_reader::wait(int timer)
+  {
+    if(!async_reading_)
+    {
+      return;
+    }
+
+    uint32_t numbytes_copied(0);
+    DWORD res = GetOverlappedResult(file_.get(),&overlapped_,(LPDWORD)&numbytes_copied,TRUE);
+    // \83G\83\89\81[\83`\83F\83b\83N
+    if(!res)
+    {
+      DWORD err = GetLastError();
+      switch (err) 
+      { 
+      case ERROR_HANDLE_EOF: 
+        { 
+          // Handle an end of file
+          if(repeat_mode_){
+            reset_data_position();
+          }
+          throw file_eof_exception(win32_error_exception::get_last_error_str(err));
+          break;
+        } 
+      default:
+        {
+          throw file_error_exception(win32_error_exception::get_last_error_str(err));
+        }
+      }
+    }
+
+    ResetEvent(event_.get());
+    offset_ += numbytes_copied;
+    data_bytes_remaining_ -= numbytes_copied;
+    async_reading_ = false;
+  };
+
+
 }
index 16a7deb..a003a72 100644 (file)
 
   ==============================================================================
 */
+#include <audioclient.h>
+#include "exception.h"
+#include "audio_source.h"
+#include "sf_memory.h"
+
 namespace sf {
-class async_reader
-{
-public:
-  async_reader();
-  ~async_reader();
-private:
-  struct impl;
-  std::shared_ptr<impl> impl_;
-};
+  class async_reader : public audio_source
+  {
+  public:
+    struct file_error_exception : public sf::exception 
+    {
+      file_error_exception(const std::wstring& reason) : exception(reason) {};
+      file_error_exception(const wchar_t* reason) : exception(std::wstring(reason)) {};
+    };
+
+    struct file_eof_exception : public sf::exception
+    {
+      file_eof_exception(const std::wstring& reason) : exception(reason) {};
+      file_eof_exception(const wchar_t* reason) : exception(std::wstring(reason)) {};
+
+    };
+    async_reader(const std::wstring file_name, bool repeat_mode);
+    ~async_reader();
+    bool stream_status() { return stream_status_; };
+    WAVEFORMATEXTENSIBLE &get_wave_format()
+    {
+      return  wfx_ ;
+    };
+
+    bool more_data_available()
+    {
+      return (stream_status_  &&
+        (repeat_mode_  || data_bytes_remaining_ > 0));
+    };
+
+    uint64_t total_data_bytes() { return total_data_bytes_; }
+    uint64_t data_bytes_remaining() { return data_bytes_remaining_; }
+    void seek(uint64_t pos);
+    void read_data(BYTE *buffer, uint64_t numbytes_to_copy);
+    void read_data_sync(BYTE *buffer, uint64_t numbytes_to_copy);
+
+    void reset_data_position();
+    HANDLE raw_handle() { return file_.get();};
+    void wait(int timer = INFINITE);
+  private:
+
+    handle_holder file_;
+    handle_holder event_;
+    bool stream_status_;
+    uint64_t data_chunk_position;
+    uint64_t total_data_bytes_;
+    uint64_t data_bytes_remaining_;
+    uint64_t offset_;
+    WAVEFORMATEXTENSIBLE wfx_;
+    bool repeat_mode_;
+    bool async_reading_;
+    OVERLAPPED overlapped_;
+
+  };
+
+
 }
 
diff --git a/async/audio_source.h b/async/audio_source.h
new file mode 100644 (file)
index 0000000..b678b11
--- /dev/null
@@ -0,0 +1,40 @@
+#pragma once
+/*
+  ==============================================================================
+
+   This file is part of the async
+   Copyright 2005-11 by Satoshi Fujiwara.
+
+   async can be redistributed and/or modified under the terms of the
+   GNU General Public License, as published by the Free Software Foundation;
+   either version 2 of the License, or (at your option) any later version.
+
+   async is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with async; if not, visit www.gnu.org/licenses or write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
+   Boston, MA 02111-1307 USA
+
+  ==============================================================================
+*/
+namespace sf{
+
+class audio_source
+{
+public:
+    virtual bool stream_status() = 0;
+    virtual WAVEFORMATEXTENSIBLE &get_wave_format() = 0;
+    virtual bool more_data_available() = 0;
+    virtual void read_data(BYTE *buffer, uint64_t numbytes) = 0;
+    virtual void reset_data_position() = 0;
+    virtual uint64_t total_data_bytes() = 0;
+    virtual void seek(uint64_t pos) = 0;
+    virtual uint64_t data_bytes_remaining() = 0;
+    virtual HANDLE raw_handle() = 0;
+    virtual void wait(int timer = -1) = 0;
+};
+}
\ No newline at end of file
index 722072d..2d382eb 100644 (file)
@@ -96,4 +96,14 @@ win32_error_exception::win32_error_exception()
        //Logger::outputDebugPrintf(L"Win32 Error %x %s",hresult_,mem.Get() );
 };
 
+std::wstring& win32_error_exception::get_last_error_str(uint32_t err)
+{
+//     DWORD err = ::GetLastError();
+  std::wstring err_str;
+       local_memory<wchar_t> mem;
+       DWORD rv =  FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,0,err,0,(LPWSTR)&mem,0,0);
+       err_str = mem.get();
+  return err_str;
+}
+
 }
\ No newline at end of file
index b8c3051..af24751 100644 (file)
@@ -25,7 +25,8 @@ namespace sf
                virtual ~win32_error_exception() {};
                uint32_t hresult() {return hresult_;}
                std::wstring& error() {return error_;}
-       private:
+    static std::wstring& get_last_error_str(uint32_t err = ::GetLastError());
+  private:
                uint32_t hresult_;
                std::wstring error_;
        };
index 6ce1905..482cd12 100644 (file)
@@ -281,9 +281,9 @@ struct toplevel_window::impl : public base_win32_dialog_t
         case TB_ENDTRACK :
 #ifdef _DEBUG
           wdout << L"TB_ENDTRACK" << std::endl;
+#endif
            application::instance()->set_play_position(SendMessage(GetDlgItem(hwnd_,IDC_SLIDER), TBM_GETPOS, 0, 0) * application::instance()->get_data_size() / SLIDER_MAX); 
 
-#endif
           thumb_start_ = false;
           break;
         case TB_PAGEUP:
@@ -452,7 +452,7 @@ struct toplevel_window::impl : public base_win32_dialog_t
   
   void init_control()
   {
-     SendMessage(GetDlgItem(hwnd_,IDC_SLIDER), TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(0, 30000));
+     SendMessage(GetDlgItem(hwnd_,IDC_SLIDER), TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(0, SLIDER_MAX));
      //slider_.attach(GetDlgItem(hwnd_,IDC_SLIDER));
   }
 
index b2262fa..9e0e0ce 100644 (file)
 */
 
 #include "StdAfx.h"
+#if _DEBUG
+#define _CRTDBG_MAP_ALLOC
+#include <crtdbg.h>
+#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
+#endif
 #include "sf_memory.h"
 #include "audio_base.h"
 #include "wasapi.h"
 
-
 namespace sf{
   wasapi_shared_timer::wasapi_shared_timer(::WAVEFORMATEXTENSIBLE& wfx) 
     : is_enabled_(false),position_(0),is_start_(false)/*,buffer_control_event_(::CreateEventEx(NULL, NULL, 0, EVENT_MODIFY_STATE | SYNCHRONIZE))*/
index ffe2afb..86a1449 100644 (file)
@@ -1,4 +1,29 @@
-// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+/*
+  ==============================================================================
+
+   This file is part of the async
+   Copyright 2005-11 by Satoshi Fujiwara.
+
+   async can be redistributed and/or modified under the terms of the
+   GNU General Public License, as published by the Free Software Foundation;
+   either version 2 of the License, or (at your option) any later version.
+
+   async is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with async; if not, visit www.gnu.org/licenses or write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
+   Boston, MA 02111-1307 USA
+
+  ==============================================================================
+*/
+
+// SDKのサンプルを改造した作ったもの。内容はほぼそのまま。
+
+// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
 // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
 // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
 // PARTICULAR PURPOSE.
@@ -12,6 +37,7 @@
 //   Wave file reader.
 //
 //-----------------------------------------------------------
+
 #include "stdafx.h"
 #include <stdio.h>
 #include <assert.h>
index c7c3af6..b43a48a 100644 (file)
 */
 #include <audioclient.h>
 #include "exception.h"
+#include "audio_source.h"
 
 namespace sf{
 
-class audio_source
-{
-public:
-    virtual bool stream_status() = 0;
-    virtual WAVEFORMATEXTENSIBLE &get_wave_format() = 0;
-    virtual bool more_data_available() = 0;
-    virtual void read_data(BYTE *buffer, uint64_t numbytes) = 0;
-    virtual void reset_data_position() = 0;
-    virtual uint64_t total_data_bytes() = 0;
-    virtual void seek(uint64_t pos) = 0;
-    virtual uint64_t data_bytes_remaining() = 0;
-    virtual HANDLE raw_handle() = 0;
-};
-
 class wave_file_reader : public audio_source
 {
     struct exception : public sf::exception
@@ -77,6 +64,10 @@ public:
     void read_data(BYTE *buffer, uint64_t numbytes);
     void reset_data_position();
     HANDLE raw_handle() { return reinterpret_cast<HANDLE>(file_);};
+    void wait(int timer = -1) {return;};
+
 };
+
+
 }