gtkIOStream  1.7.0
GTK+ << C++ IOStream operators for GTK+. Now with ORBing, numerical computation, audio client and more ...
Playback.H
Go to the documentation of this file.
1 /* Copyright 2000-2018 Matt Flax <flatmax@flatmax.org>
2  This file is part of GTK+ IOStream class set
3 
4  GTK+ IOStream is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or
7  (at your option) any later version.
8 
9  GTK+ IOStream is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You have received a copy of the GNU General Public License
15  along with GTK+ IOStream
16 */
17 #ifndef PLAYBACK_H
18 #define PLAYBACK_H
19 
20 #include <ALSA/ALSA.H>
21 #include <vector>
22 
23 namespace ALSA {
26  class Playback : public Stream {
27  std::vector<void *> buffer;
28  public:
29  Playback(const char *devName) : Stream() {
30  open(devName);
31  }
32 
34  open();
35  }
36 
37  virtual ~Playback(void){
38  }
39 
40  void open(const char *devName="default"){
41  int ret=Stream::init(devName, SND_PCM_STREAM_PLAYBACK, block ? 0 : SND_PCM_NONBLOCK);
42  if (ret < 0) {
43  std::cerr<<"Playback :: Playback : open error: "<< snd_strerror(ret)<<std::endl;
44  assert("open error");
45  }
46  }
47 
54  int writeBuf(void **buffers, size_t len, int ch){
55  PCM_NOT_OPEN_CHECK(getPCM()) // check pcm is open
56  std::cout<<"ch = "<<ch<<"\n";
57  if (buffer.size()!=ch)
58  buffer.resize(ch);
59  for (int i=0;i<ch;i++)
60  buffer[i]=buffers[i];
61  int ret=0;
62  while ((len-=ret) > 0) {
63  // dumpStatus();
64  ret = snd_pcm_writen(getPCM(), &buffer[0], len);
65  std::cout<<"ret "<<ret<<std::endl;
66  if (ret == -EAGAIN || (ret>=0 && ret<len))
67  wait();
68  if (ret<0 && ret!=-EAGAIN){
69  printf("Write error: %s\n", snd_strerror(ret));
70  return ret;
71  }
72  std::cout<<"ch = "<<ch<<"\n";
73  for (int i=0;i<ch;i++){
74  char *c=(char*)buffer[i];
75  c+=ret*4;
76  buffer[i]=(void*)c;
77  }
78  }
79  return 0;
80  }
81 
86  template <typename Derived>
87  int writeBufN(const Eigen::DenseBase<Derived> &audioData){
88  std::cout<<"non interleaved"<<std::endl;
89  if (buffer.size()!=audioData.cols())
90  buffer.resize(audioData.cols());
91  for (int i=0;i<audioData.cols();i++)
92  buffer[i]=(void*)audioData.col(i).data();
93  return writeBuf(&buffer[0], audioData.rows(), audioData.cols());
94  }
95 
101  int writeBuf(char *bufferIn, size_t len){
102  PCM_NOT_OPEN_CHECK_NO_PRINT(getPCM(), int) // check pcm is open
103  int bytes_per_frame = getFormatPhysicalWidth() * getChannels()/8;
104  //std::cout<<"getFormatPhysicalWidth()/8 "<<getFormatPhysicalWidth()/8<<" getChannels() "<<getChannels()<<'\n';
105  // PCM_NOT_OPEN_CHECK(getPCM()) // check pcm is open
106  int ret=snd_pcm_writei(getPCM(), (void *)bufferIn, len); // first time through - allow for starting if required
107  if (prepared())
108  if ((ret=start())<0)
109  return ALSADebug().evaluateError(ret);
110 
111  if (ret==-EAGAIN)
112  ret=0;
113  while ((len-=ret) > 0) {
114  if ((ret>=0 && ret<len) && block!=0)
115  wait(1);
116  if (ret<0)
117  if (ret==-EPIPE)
118  ALSADebug().evaluateError(ret," writeBuf underrun\n");
119  else
120  return ALSADebug().evaluateError(ret," in writeBuf main loop, unidentified error.\n");
121  bufferIn += ret*bytes_per_frame;
122 
123  ret = snd_pcm_writei(getPCM(), (void *)bufferIn, len);
124  if (ret==-EAGAIN)
125  ret=0;
126  }
127  return 0;
128  }
129 
134  template <typename Derived>
135  int writeBuf(const Eigen::DenseBase<Derived> &audioData){
136  return writeBuf((char*)&audioData(0,0), audioData.rows());
137  }
138 
143  template <typename Derived>
144  Playback& operator<<(const Eigen::DenseBase<Derived> &audioData){
145  int ret=writeBuf((char*)&audioData(0,0), audioData.rows());
146  if (ret<0)
147  throw;
148  return *this;
149  }
150  };
151 }
152 #endif //PLAYBACK_H
int writeBufN(const Eigen::DenseBase< Derived > &audioData)
Definition: Playback.H:87
std::vector< void * > buffer
Non interleaved buffer pointers.
Definition: Playback.H:27
#define PCM_NOT_OPEN_CHECK_NO_PRINT(pcm, type)
Definition: ALSA.H:28
virtual snd_pcm_t * getPCM()
Definition: PCM.H:42
int init(const char *device, snd_pcm_stream_t streamType, bool blockIn)
Definition: Stream.H:36
Definition: ALSA.H:26
bool prepared()
Definition: PCM.H:182
virtual int evaluateError(int errorNum)
Definition: ALSADebug.H:61
void open(const char *devName="default")
Definition: Playback.H:40
#define PCM_NOT_OPEN_CHECK(pcm)
Definition: ALSA.H:30
int writeBuf(const Eigen::DenseBase< Derived > &audioData)
Definition: Playback.H:135
int getFormatPhysicalWidth()
Definition: Hardware.H:202
int start()
Definition: PCM.H:166
Definition: IIOMMap.H:56
int wait(int timeOut=1000)
Definition: Stream.H:158
int writeBuf(char *bufferIn, size_t len)
Definition: Playback.H:101
Playback(const char *devName)
Definition: Playback.H:29
int getChannels()
Definition: Hardware.H:222
virtual ~Playback(void)
Definition: Playback.H:37
int writeBuf(void **buffers, size_t len, int ch)
Definition: Playback.H:54
gtkIOStream: /tmp/gtkiostream/include/ALSA/Playback.H Source File
GTK+ IOStream  Beta