home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
MM1
/
SOUNDUTILS
/
tracker.4.6.lzh
/
TRACKER4.6
/
Hpux
/
3_audio.c
next >
Wrap
Text File
|
1994-11-24
|
11KB
|
467 lines
/* -*-C-*-
vi:ts=3 sw=3:
*******************************************************************************
*
* File: hpux_audio.c
* RCS: $Header: $
* Description: HP-UX audio hardware interface for tracker
* Author: Darryl Okahata (darrylo@sr.hp.com)
* Created: Thu Dec 16 12:09:53 1993
* Modified: Mon Dec 20 12:17:02 1993 (Darryl Okahata) darrylo@mina
* Language: C
* Package: N/A
* Status: Experimental
*
* (C) Copyright 1993, Hewlett-Packard, all rights reserved.
*
*******************************************************************************
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <audio/Alib.h>
#include "defs.h"
#include "extern.h"
#define abs(x) ((x) < 0 ? -(x) : (x))
#define STEREO_CHANNELS (ALeftOutputChMask | ARightOutputChMask)
extern AGainDB volume; /* volume in dB -- in main.c */
extern char use_speaker; /* in main.c */
LOCAL Audio *audio;
LOCAL ADataFormat *available_formats;
LOCAL long available_formats_len;
LOCAL AOutputChMask available_channels;
LOCAL AByteOrder byte_order;
LOCAL AudioAttributes audio_attributes;
LOCAL AGainEntry gain_entry[4];
LOCAL SSPlayParams stream_parameters;
LOCAL ATransID xid;
LOCAL SStream audio_stream;
LOCAL int stream_socket;
LOCAL int stereo;
LOCAL int primary, secondary = 512;
LOCAL ADataFormat audio_format;
LOCAL int index, max_index;
LOCAL long buffer_size;
LOCAL char *buffer;
LOCAL short *sbuffer;
LOCAL int round_sampling_rate(audio, f)
Audio *audio;
int f;
{
int best = 0;
int i;
for (i = 0; i < audio->n_sampling_rate; i++) {
if (abs(audio->sampling_rate_list[i] - f) < abs(best - f)) {
best = audio->sampling_rate_list[i];
}
}
return best;
}
LOCAL format_available(fmt)
ADataFormat fmt;
{
int i;
for (i = 0; i < available_formats_len; ++i) {
if (available_formats[i] == fmt) {
break;
}
}
if (i >= available_formats_len) {
return (0);
}
return (1);
}
void set_mix(percent)
int percent;
{
percent *= 256;
percent /= 100;
primary = percent;
secondary = 512 - percent;
}
/*
* It would be nice if we could use AGetErrorText(), but this requires that
* an audio pointer be passed to it, and this pointer could be NULL.
*/
LOCAL void die(msg, error)
char *msg;
AError error;
{
char *errbuf, buf[1000]; /* memory is cheap, life is short */
if (msg == NULL) {
msg = "";
}
switch (error) {
case AENoError:
errbuf = "(No audio error -- huh? This should never happen!)";
break;
case AESystemCall:
errbuf = "System call error";
break;
case AEBadAudio:
errbuf = "Bad audio";
break;
case AEBadValue:
errbuf = "Bad audio value";
break;
case AEHostNotFound:
errbuf = "Audio host not found";
break;
case AENoSuchAudioNumber:
errbuf = "No such audio number";
break;
case AEBadFileFormat:
errbuf = "Bad audio file format";
break;
case AEBadDataFormat:
errbuf = "Bad audio data format";
break;
case AEFileNotFound:
errbuf = "Audio file not found";
break;
case AEBadLinkID:
errbuf = "Audio bad link ID";
break;
case AEBadGainMatrix:
errbuf = "Bad audio gain matrix";
break;
case AEBadFileHdr:
errbuf = "Bad audio file header";
break;
case AEUnrecognizableFormat:
errbuf = "Unrecognizable audio format";
break;
case AEBadAttribute:
errbuf = "Bad audio attribute";
break;
case AEBadOffset:
errbuf = "Audio bad offset";
break;
case AEBadTransactionID:
errbuf = "Bad audio transaction ID";
break;
case AECantDetermineFormat:
errbuf = "Audio can't determine format";
break;
case AEOutOfMemory:
errbuf = "out of memory (audio)";
break;
case AEOpenFailed:
errbuf = "Audio open failed";
break;
case AEBadSamplingRate:
errbuf = "Bad audio sampling rate";
break;
case AEBadSoundBucket:
errbuf = "Audio bad sound bucket";
break;
case AEBadSoundStream:
errbuf = "Audio bad sound stream";
break;
case AETransactionBusy:
errbuf = "Audio transaction busy";
break;
case AEllbdNotStarted:
errbuf = "llbd daemon not running";
break;
case AERPCFailed:
errbuf = "Audio RPC failed";
break;
case AELibraryMismatch:
errbuf = "Audio library mismatch";
break;
default:
sprintf(buf, "(unknown audio error %d)", (int) error);
errbuf = buf;
break;
}
notice(msg);
end_all(errbuf);
}
int open_audio(freq, stereo_flag)
int freq;
int stereo_flag;
{
long status_return;
AudioAttrMask valid_attributes;
char *speaker;
int dsize, i;
stereo = stereo_flag;
if ((audio = AOpenAudio(NULL, &status_return)) == NULL) {
die("could not open audio: ", status_return);
}
available_formats = ADataFormats(audio);
available_formats_len = ANumDataFormats(audio);
if (format_available(ADFLin16)) {
audio_format = ADFLin16;
dsize = 2; /* for ADFLin16 */
} else if (format_available(ADFLin8)) {
audio_format = ADFLin8;
dsize = 1; /* for ADFLin8 */
} else {
end_all("Neither ADFLin16/ADFLin8 supported by the audio device");
}
available_channels = AOutputChannels(audio);
valid_attributes = ASDataFormatMask | ASBitsPerSampleMask |
ASSamplingRateMask | ASChannelsMask;
audio_attributes = *ABestAudioAttributes(audio);
audio_attributes.type = ATSampled;
audio_attributes.attr.sampled_attr.data_format = ADFLin16;
audio_attributes.attr.sampled_attr.bits_per_sample = 16;
if (freq <= 0) {
/*
* Use value closest to CD-quality audio
*/
freq = 44100;
}
freq = round_sampling_rate(audio, freq);
audio_attributes.attr.sampled_attr.sampling_rate = freq;
audio_attributes.attr.sampled_attr.duration.type = ATTFullLength;
valid_attributes |= ASDurationMask;
if (stereo &&
((available_channels & (STEREO_CHANNELS)) == STEREO_CHANNELS)) {
audio_attributes.attr.sampled_attr.channels = 2;
audio_attributes.attr.sampled_attr.interleave = 1;
valid_attributes |= ASInterleaveMask;
} else {
audio_attributes.attr.sampled_attr.channels = 1;
}
/*
* Select attributes for playback
*/
AChoosePlayAttributes(audio, ABestAudioAttributes(audio),
valid_attributes, &audio_attributes,
&byte_order, &status_return);
if (byte_order != AMSBFirst) {
end_all("Little endian byte ordering not supported");
}
/*
* Use the external jack, unless the user overrides this on the
* command-line, or SPEAKER is set. (The command line stuff is done in
* main.c.)
*/
if ((speaker = getenv( "SPEAKER" )) != NULL) {
if ((*speaker == 'i') || (*speaker == 'I')) {
use_speaker = 1;
}
}
stream_parameters.priority = APriorityNormal;
switch(audio_attributes.attr.sampled_attr.channels) {
case 1:
gain_entry[0].u.o.out_ch = AOCTMono;
gain_entry[0].gain = volume;
gain_entry[0].u.o.out_dst =
(use_speaker) ? AODTMonoIntSpeaker : AODTMonoJack;
break;
case 2:
default: /* assume no more than 2 channels */
gain_entry[0].u.o.out_ch = AOCTLeft;
gain_entry[0].gain = volume;
gain_entry[0].u.o.out_dst =
(use_speaker) ? AODTLeftIntSpeaker : AODTLeftJack;
gain_entry[1].u.o.out_ch = AOCTRight;
gain_entry[1].gain = volume;
gain_entry[1].u.o.out_dst =
(use_speaker) ? AODTRightIntSpeaker : AODTRightJack;
break;
}
stream_parameters.gain_matrix.type = AGMTOutput; /* gain matrix */
stream_parameters.gain_matrix.num_entries =
audio_attributes.attr.sampled_attr.channels;
stream_parameters.gain_matrix.gain_entries = gain_entry;
stream_parameters.play_volume = AUnityGain; /* play volume */
stream_parameters.event_mask = 0; /* don't solicit any
events */
/*
* create an audio stream
*/
xid = APlaySStream(audio, valid_attributes, &audio_attributes,
&stream_parameters, &audio_stream, NULL);
/*
* create a stream socket
*/
stream_socket = socket(AF_INET, SOCK_STREAM, 0);
if(stream_socket < 0) {
end_all("Socket creation failed");
}
/*
* connect the stream socket to the audio stream port
*/
status_return = connect(stream_socket,
(struct sockaddr *)&audio_stream.tcp_sockaddr,
sizeof(struct sockaddr_in));
if(status_return < 0) {
end_all("Connect failed");
}
buffer_size = dsize * audio_attributes.attr.sampled_attr.channels *
audio_attributes.attr.sampled_attr.sampling_rate;
buffer = (char *) malloc(buffer_size);
sbuffer = (short *) buffer;
if (!buffer) {
end_all("Unable to allocate memory for buffer");
}
switch (audio_format) {
case ADFLin16:
max_index = buffer_size / 2 - 1;
break;
case ADFLin8:
max_index = buffer_size - 1;
break;
default:
end_all("Bad");
break;
}
max_index = buffer_size;
return (audio_attributes.attr.sampled_attr.sampling_rate);
}
void set_synchro(s)
int s;
{
/* not implemented */
}
int update_frequency()
{
/* not implemented */
return 0;
}
void flush_buffer()
{
int len_written, len_left;
char *buf;
len_left = index * 2;
buf = buffer;
while (len_left > 0) {
if((len_written = write(stream_socket, buf, len_left)) < 0) {
end_all("Write failed");
}
len_left -= len_written;
buf += len_written;
}
index = 0;
}
void output_samples(left, right)
int left, right;
{
if (index >= max_index) {
flush_buffer();
}
if (stereo) {
int r, l;
r = (left * primary + right * secondary) / 256;
l = (right * primary + left * secondary) / 256;
switch (audio_format) {
case ADFLin16:
sbuffer[index++] = r;
sbuffer[index++] = l;
break;
case ADFLin8:
buffer[index++] = r / 256 + ((r & 0x80) ? 1 : 0);
buffer[index++] = l / 256 + ((l & 0x80) ? 1 : 0);
break;
default:
break;
}
} else {
switch (audio_format) {
case ADFLin16:
sbuffer[index++] = left + right;
break;
case ADFLin8:
buffer[index++] = left + right;
break;
default:
break;
}
}
}
void discard_buffer()
{
/* not implemented -- is this needed??? */
}
void close_audio()
{
close(stream_socket);
/*
* set close mode to prevent playback from stopping
* when we close audio connection
*/
ASetCloseDownMode(audio, AKeepTransactions, NULL);
/*
* That's all, folks!
*/
ACloseAudio(audio, NULL);
audio = NULL;
}
/*
* Local Variables:
* c-indent-level: 4
* c-continued-statement-offset: 4
* c-brace-offset: -4
* c-argdecl-indent: 0
* c-label-offset: -4
* End:
*/