File: obuffer_next.cc

package info (click to toggle)
maplay 1.2b-5
  • links: PTS
  • area: main
  • in suites: slink
  • size: 432 kB
  • ctags: 441
  • sloc: cpp: 5,421; sh: 97; makefile: 86
file content (165 lines) | stat: -rw-r--r-- 4,433 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
/*
 *  @(#) obuffer_next.cc 1.1, last edit: 27 Oct 1994 17:20:53
 *  @(#) Copyright (C) 1993, 1994 Tobias Bading (bading@cs.tu-berlin.de)
 *  @(#) Berlin University of Technology
 *
 *  NeXTStep class written at the end of June 1994 by
 *  Pete French (pete@ohm.york.ac.uk) and Ian Stepehnson (ian@ohm.york.ac.uk)
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it 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.
 *
 *  This program 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 this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

/*
 *  New in maplay 1.3
 */

// This code is messy. I'm not proud of it, but it does work.
// Bear in mind that it is multi-threaded or it will make no
// sense whatsoever. I apologise to any C++ programmers. All
// the C++ I know was learnt from reading these files. Hence
// it bears a striking resemblance to the Linux code...
//
// -Pete French.

extern "Objective-C" {
#import <appkit/appkit.h>
#import <soundkit/NXPlayStream.h>
#import <soundkit/NXSoundOut.h>
#import <machkit/NXLock.h>
};

float	NeXTObuffer::sample_rate;
int	NeXTObuffer::chans;

extern 	char *next_sound_host;    // from -H argument

static id song_lock_id, queue_lock_id;
static id device_id, player_id;
static int queue_length, drain_queue;


@interface queue_counter:Object
{
}
- soundStream:sender didCompleteBuffer:(int)tag;
@end


@implementation queue_counter
- soundStream:sender didCompleteBuffer:(int)tag
{
[queue_lock_id lock];
queue_length--;
if(queue_length>MAX_QUEUE_LENGTH)
 [queue_lock_id unlockWith:CANNOT_QUEUE];
else
 [queue_lock_id unlockWith:CAN_QUEUE];
if((drain_queue) && (queue_length==0))
 [song_lock_id unlock];
return self;
}
@end


NeXTObuffer::NeXTObuffer (uint32 number_of_channels, Header *header)
{
#ifdef DEBUG
  if (!number_of_channels || number_of_channels > MAXCHANNELS)
  {
    cerr << "NeXTObuffer: 0 < number of channels < " << MAXCHANNELS << "!\n";
    exit (1);
  }
#endif
  sample_rate=(float)header->frequency();
  chans=number_of_channels;
  if((sample_rate!=SND_RATE_HIGH) && (sample_rate!=SND_RATE_LOW))
  {
    cerr << "NeXT cannot play at sample rate " << sample_rate << "\n";
    exit (1);
  }
  for (int i = 0; i < number_of_channels; ++i)
    bufferp[i] = buffer + i;

  // get a device and player
  device_id=[NXSoundOut alloc];
  player_id=[NXPlayStream alloc];

  // initialise device and attach to player
  if(next_sound_host!=NULL)
    {
     if([device_id initOnHost:next_sound_host]==nil)
     {
       cerr << "Could not get sound device on " << next_sound_host << "\n";
       exit(1);
     }
    }
  else
    [device_id init];
  [player_id initOnDevice:device_id];

  // setup the queue and queue counter
  queue_lock_id=[[NXConditionLock alloc] initWith:CAN_QUEUE];
  queue_length=0;
  drain_queue=0;
  [player_id setDelegate:[[queue_counter alloc] init]];
  
  //and start the player
  song_lock_id=[[NXLock alloc] init];
  [song_lock_id lock];
  [player_id activate];
}


void NeXTObuffer::really_write_buffer (int16 **bp, int16 *bf)
{
  int length = (int)((char *)bp[0] - (char *)bf);
  [queue_lock_id lockWhen:CAN_QUEUE];
  queue_length++;
  if(queue_length>MAX_QUEUE_LENGTH)
   [queue_lock_id unlockWith:CANNOT_QUEUE];
  else
   [queue_lock_id unlockWith:CAN_QUEUE];
  [player_id playBuffer:bf
             size:length
             tag:(int)1
             channelCount:chans
             samplingRate:sample_rate];
  for (int i = 0; i < chans; ++i)
    bp[i] = bf + i;
}


NeXTObuffer::~NeXTObuffer (void)
{
  NeXTObuffer::really_write_buffer(bufferp,buffer);
  drain_queue=1;
  [song_lock_id lock];
}


void NeXTObuffer::append (uint32 channel, int16 value)
{
#ifdef DEBUG
  if (channel >= chans)
  {
    cerr << "illegal channelnumber in NeXTObuffer::append()!\n";
    exit (1);
  }
#endif
  if (bufferp[channel] - buffer >= OBUFFERSIZE)
   NeXTObuffer::really_write_buffer(bufferp,buffer);
  *bufferp[channel] = htons(value);
  bufferp[channel] += chans;
}